diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:14 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:14 -0800 |
commit | 05806d7af62e07c6225b2e7103a1b115ecf6c9ad (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /tools/soslim | |
parent | 094268cf8cb37b9d904c8a1e3559cdd46d73cf66 (diff) | |
download | build-05806d7af62e07c6225b2e7103a1b115ecf6c9ad.zip build-05806d7af62e07c6225b2e7103a1b115ecf6c9ad.tar.gz build-05806d7af62e07c6225b2e7103a1b115ecf6c9ad.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'tools/soslim')
-rw-r--r-- | tools/soslim/Android.mk | 49 | ||||
-rw-r--r-- | tools/soslim/cmdline.c | 141 | ||||
-rw-r--r-- | tools/soslim/cmdline.h | 16 | ||||
-rw-r--r-- | tools/soslim/common.c | 35 | ||||
-rw-r--r-- | tools/soslim/common.h | 49 | ||||
-rw-r--r-- | tools/soslim/debug.c | 40 | ||||
-rw-r--r-- | tools/soslim/debug.h | 88 | ||||
-rw-r--r-- | tools/soslim/main.c | 360 | ||||
-rw-r--r-- | tools/soslim/prelink_info.c | 106 | ||||
-rw-r--r-- | tools/soslim/prelink_info.h | 9 | ||||
-rw-r--r-- | tools/soslim/soslim.c | 528 | ||||
-rw-r--r-- | tools/soslim/soslim.h | 32 | ||||
-rw-r--r-- | tools/soslim/symfilter.c | 242 | ||||
-rw-r--r-- | tools/soslim/symfilter.h | 50 |
14 files changed, 0 insertions, 1745 deletions
diff --git a/tools/soslim/Android.mk b/tools/soslim/Android.mk deleted file mode 100644 index 60a860a..0000000 --- a/tools/soslim/Android.mk +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2005 The Android Open Source Project -# -# Android.mk for soslim -# - -LOCAL_PATH:= $(call my-dir) - -ifeq ($(TARGET_ARCH),arm) -include $(CLEAR_VARS) - -LOCAL_LDLIBS += -ldl -LOCAL_CFLAGS += -O2 -g -LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline -LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror -LOCAL_CFLAGS += -DBIG_ENDIAN=1 -LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS -LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS -LOCAL_CFLAGS += -DDEBUG -LOCAL_CFLAGS += -DSTRIP_STATIC_SYMBOLS -LOCAL_CFLAGS += -DMOVE_SECTIONS_IN_RANGES - -ifeq ($(HOST_OS),windows) -# Cygwin stat does not support ACCESSPERMS bitmask -LOCAL_CFLAGS += -DACCESSPERMS=0777 -LOCAL_LDLIBS += -lintl -endif - -LOCAL_SRC_FILES := \ - cmdline.c \ - common.c \ - debug.c \ - soslim.c \ - main.c \ - prelink_info.c \ - symfilter.c - -LOCAL_C_INCLUDES:= \ - $(LOCAL_PATH)/ \ - external/elfutils/lib/ \ - external/elfutils/libelf/ \ - external/elfutils/libebl/ \ - external/elfcopy/ - -LOCAL_STATIC_LIBRARIES := libelfcopy libelf libebl libebl_arm #dl - -LOCAL_MODULE := soslim - -include $(BUILD_HOST_EXECUTABLE) -endif #TARGET_ARCH==arm diff --git a/tools/soslim/cmdline.c b/tools/soslim/cmdline.c deleted file mode 100644 index c2d5e71..0000000 --- a/tools/soslim/cmdline.c +++ /dev/null @@ -1,141 +0,0 @@ -#include <debug.h> -#include <cmdline.h> -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <string.h> -#include <ctype.h> - -extern char *optarg; -extern int optind, opterr, optopt; - -static struct option long_options[] = -{ - {"verbose", no_argument, 0, 'V'}, - {"quiet", no_argument, 0, 'Q'}, - {"shady", no_argument, 0, 'S'}, - {"print", no_argument, 0, 'p'}, - {"help", no_argument, 0, 'h'}, - {"outfile", required_argument, 0, 'o'}, - {"filter", required_argument, 0, 'f'}, - {"dry", no_argument, 0, 'n'}, - {"strip", no_argument, 0, 's'}, - {0, 0, 0, 0}, -}; - -/* This array must parallel long_options[] */ -static -const char *descriptions[sizeof(long_options)/sizeof(long_options[0])] = { - "print verbose output", - "suppress errors and warnings", - "patch ABS symbols whose values coincide with section starts and ends", - "print the symbol table (if specified, only -V is allowed)", - "this help screen", - "specify an output file (if not provided, input file is modified)", - "specify a symbol-filter file", - "dry run (perform all calculations but do not modify the ELF file)", - "strip debug sections, if they are present" -}; - -void print_help(void) -{ - fprintf(stdout, - "invokation:\n" - "\tsoslim file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] " - "[-Vpn]\n" - "or\n" - "\tsoslim -h\n\n"); - fprintf(stdout, "options:\n"); - struct option *opt = long_options; - const char **desc = descriptions; - while (opt->name) { - fprintf(stdout, "\t-%c/--%-15s %s\n", - opt->val, - opt->name, - *desc); - opt++; - desc++; - } -} - -int get_options(int argc, char **argv, - char **outfile, - char **symsfile, - int *print_symtab, - int *verbose, - int *quiet, - int *shady, - int *dry_run, - int *strip_debug) -{ - int c; - - ASSERT(outfile); - *outfile = NULL; - ASSERT(symsfile); - *symsfile = NULL; - ASSERT(print_symtab); - *print_symtab = 0; - ASSERT(verbose); - *verbose = 0; - ASSERT(quiet); - *quiet = 0; - ASSERT(shady); - *shady = 0; - ASSERT(dry_run); - *dry_run = 0; - ASSERT(strip_debug); - *strip_debug = 0; - - while (1) { - /* getopt_long stores the option index here. */ - int option_index = 0; - - c = getopt_long (argc, argv, - "QVSphi:o:y:Y:f:ns", - long_options, - &option_index); - /* Detect the end of the options. */ - if (c == -1) break; - - if (isgraph(c)) { - INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); - } - -#define SET_STRING_OPTION(name) do { \ - ASSERT(optarg); \ - *name = strdup(optarg); \ -} while(0) - - switch (c) { - case 0: - /* If this option set a flag, do nothing else now. */ - if (long_options[option_index].flag != 0) - break; - INFO ("option %s", long_options[option_index].name); - if (optarg) - INFO (" with arg %s", optarg); - INFO ("\n"); - break; - case 'p': *print_symtab = 1; break; - case 'h': print_help(); exit(1); break; - case 'V': *verbose = 1; break; - case 'Q': *quiet = 1; break; - case 'S': *shady = 1; break; - case 'n': *dry_run = 1; break; - case 's': *strip_debug = 1; break; - case 'o': SET_STRING_OPTION(outfile); break; - case 'f': SET_STRING_OPTION(symsfile); break; - case '?': - /* getopt_long already printed an error message. */ - break; - -#undef SET_STRING_OPTION - - default: - FAILIF(1, "Unknown option"); - } - } - - return optind; -} diff --git a/tools/soslim/cmdline.h b/tools/soslim/cmdline.h deleted file mode 100644 index bfc431e..0000000 --- a/tools/soslim/cmdline.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CMDLINE_H -#define CMDLINE_H - -void print_help(void); - -int get_options(int argc, char **argv, - char **outfile, - char **symsfile, - int *print_symtab, - int *verbose, - int *quiet, - int *shady, - int *dry_run, - int *strip_debug); - -#endif/*CMDLINE_H*/ diff --git a/tools/soslim/common.c b/tools/soslim/common.c deleted file mode 100644 index b90cf41..0000000 --- a/tools/soslim/common.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <stdlib.h> -#include <common.h> -#include <debug.h> - -void map_over_sections(Elf *elf, - section_match_fn_t match, - void *user_data) -{ - Elf_Scn* section = NULL; - while ((section = elf_nextscn(elf, section)) != NULL) { - if (match(elf, section, user_data)) - return; - } -} - -void map_over_segments(Elf *elf, - segment_match_fn_t match, - void *user_data) -{ - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdr; - int index; - - ehdr = elf32_getehdr(elf); - phdr = elf32_getphdr(elf); - - INFO("Scanning over %d program segments...\n", - ehdr->e_phnum); - - for (index = ehdr->e_phnum; index; index--) { - if (match(elf, phdr++, user_data)) - return; - } -} - diff --git a/tools/soslim/common.h b/tools/soslim/common.h deleted file mode 100644 index dacf930..0000000 --- a/tools/soslim/common.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include <libelf.h> -#include <elf.h> - -#define unlikely(expr) __builtin_expect (expr, 0) -#define likely(expr) __builtin_expect (expr, 1) - -#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */ - -typedef int (*section_match_fn_t)(Elf *, Elf_Scn *, void *); -void map_over_sections(Elf *, section_match_fn_t, void *); - -typedef int (*segment_match_fn_t)(Elf *, Elf32_Phdr *, void *); -void map_over_segments(Elf *, segment_match_fn_t, void *); - -typedef struct { - Elf_Scn *sect; - Elf32_Shdr *hdr; - Elf_Data *data; - size_t index; -} section_info_t; - -static inline void get_section_info(Elf_Scn *sect, section_info_t *info) -{ - info->sect = sect; - info->data = elf_getdata(sect, 0); - info->hdr = elf32_getshdr(sect); - info->index = elf_ndxscn(sect); -} - -static inline int is_host_little(void) -{ - short val = 0x10; - return ((char *)&val)[0] != 0; -} - -static inline long switch_endianness(long val) -{ - long newval; - ((char *)&newval)[3] = ((char *)&val)[0]; - ((char *)&newval)[2] = ((char *)&val)[1]; - ((char *)&newval)[1] = ((char *)&val)[2]; - ((char *)&newval)[0] = ((char *)&val)[3]; - return newval; -} - -#endif/*COMMON_H*/ diff --git a/tools/soslim/debug.c b/tools/soslim/debug.c deleted file mode 100644 index b8365af..0000000 --- a/tools/soslim/debug.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <debug.h> -#include <stdio.h> -#include <ctype.h> - -#if 0 - -#define NUM_COLS (32) - -int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) { - int num_nonprintable = 0; - int i, last; - char *pchr = (char *)b; - fputc('\n', s); - for (i = last = 0; i < len; i++) { - if (!elsize) { - if (i && !(i % 4)) fprintf(s, " "); - if (i && !(i % 8)) fprintf(s, " "); - } else { - if (i && !(i % elsize)) fprintf(s, " "); - } - - if (i && !(i % NUM_COLS)) { - while (last < i) { - if (isprint(pchr[last])) - fputc(pchr[last], s); - else { - fputc('.', s); - num_nonprintable++; - } - last++; - } - fprintf(s, " (%d)\n", i); - } - fprintf(s, "%02x", (unsigned char)pchr[i]); - } - if (i && (i % NUM_COLS)) fputs("\n", s); - return num_nonprintable; -} - -#endif diff --git a/tools/soslim/debug.h b/tools/soslim/debug.h deleted file mode 100644 index e7a2f9a..0000000 --- a/tools/soslim/debug.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -#include <stdlib.h> -#include <stdio.h> -#include <common.h> - -#ifdef DEBUG - - #define FAILIF(cond, msg...) do { \ - if (unlikely(cond)) { \ - fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \ - fprintf(stderr, ##msg); \ - exit(1); \ - } \ -} while(0) - -/* Debug enabled */ - #define ASSERT(x) do { \ - if (unlikely(!(x))) { \ - fprintf(stderr, \ - "ASSERTION FAILURE %s:%d: [%s]\n", \ - __FILE__, __LINE__, #x); \ - exit(1); \ - } \ -} while(0) - -#else - - #define FAILIF(cond, msg...) do { \ - if (unlikely(cond)) { \ - fprintf(stderr, ##msg); \ - exit(1); \ - } \ -} while(0) - -/* No debug */ - #define ASSERT(x) do { } while(0) - -#endif/* DEBUG */ - -#define FAILIF_LIBELF(cond, function) \ - FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno())); - -static inline void *MALLOC(unsigned int size) { - void *m = malloc(size); - FAILIF(NULL == m, "malloc(%d) failed!\n", size); - return m; -} - -static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) { - void *m = calloc(num_entries, entry_size); - FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size); - return m; -} - -static inline void *REALLOC(void *ptr, unsigned int size) { - void *m = realloc(ptr, size); - FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size); - return m; -} - -static inline void FREE(void *ptr) { - free(ptr); -} - -static inline void FREEIF(void *ptr) { - if (ptr) FREE(ptr); -} - -#define PRINT(x...) do { \ - extern int quiet_flag; \ - if(likely(!quiet_flag)) \ - fprintf(stdout, ##x); \ -} while(0) - -#define ERROR(x...) fprintf(stderr, ##x) - -#define INFO(x...) do { \ - extern int verbose_flag; \ - if(unlikely(verbose_flag)) \ - fprintf(stdout, ##x); \ -} while(0) - -/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */ -int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize); - -#endif/*DEBUG_H*/ diff --git a/tools/soslim/main.c b/tools/soslim/main.c deleted file mode 100644 index fa5a315..0000000 --- a/tools/soslim/main.c +++ /dev/null @@ -1,360 +0,0 @@ -/* TODO: - 1. check the ARM EABI version--this works for versions 1 and 2. - 2. use a more-intelligent approach to finding the symbol table, symbol-string - table, and the .dynamic section. - 3. fix the determination of the host and ELF-file endianness - 4. write the help screen -*/ - -#include <stdio.h> -#include <common.h> -#include <debug.h> -#include <hash.h> -#include <libelf.h> -#include <elf.h> -#include <gelf.h> -#include <cmdline.h> -#include <string.h> -#include <errno.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <soslim.h> -#include <symfilter.h> -#ifdef SUPPORT_ANDROID_PRELINK_TAGS -#include <prelink_info.h> -#endif - -/* Flag set by --verbose. This variable is global as it is accessed by the - macro INFO() in multiple compilation unites. */ -int verbose_flag = 0; -/* Flag set by --quiet. This variable is global as it is accessed by the - macro PRINT() in multiple compilation unites. */ -int quiet_flag = 0; -static void print_dynamic_symbols(Elf *elf, const char *symtab_name); - -int main(int argc, char **argv) -{ - int elf_fd = -1, newelf_fd = -1; - Elf *elf = NULL, *newelf = NULL; - char *infile = NULL; - char *outfile = NULL; - char *symsfile_name = NULL; - int print_symtab = 0; - int shady = 0; - int dry_run = 0; - int strip_debug = 0; - - /* Do not issue INFO() statements before you call get_options() to set - the verbose flag as necessary. - */ - - int first = get_options(argc, argv, - &outfile, - &symsfile_name, - &print_symtab, - &verbose_flag, - &quiet_flag, - &shady, - &dry_run, - &strip_debug); - - if ((print_symtab && (first == argc)) || - (!print_symtab && first + 1 != argc)) { - print_help(); - FAILIF(1, "You must specify an input ELF file!\n"); - } - FAILIF(print_symtab && (outfile || symsfile_name || shady), - "You cannot provide --print and --outfile, --filter options, or " - "--shady simultaneously!\n"); - FAILIF(dry_run && outfile, - "You cannot have a dry run and output a file at the same time."); - - /* Check to see whether the ELF library is current. */ - FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n"); - - if (print_symtab) { - - while (first < argc) { - infile = argv[first++]; - - INFO("Opening %s...\n", infile); - elf_fd = open(infile, O_RDONLY); - FAILIF(elf_fd < 0, "open(%s): %s (%d)\n", - infile, - strerror(errno), - errno); - INFO("Calling elf_begin(%s)...\n", infile); - elf = elf_begin(elf_fd, ELF_C_READ, NULL); - FAILIF_LIBELF(elf == NULL, elf_begin); - - /* libelf can recognize COFF and A.OUT formats, but we handle only - ELF. */ - FAILIF(elf_kind(elf) != ELF_K_ELF, - "Input file %s is not in ELF format!\n", - infile); - - /* Make sure this is a shared library or an executable. */ - { - GElf_Ehdr elf_hdr; - INFO("Making sure %s is a shared library or an executable.\n", - infile); - FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr), gelf_getehdr); - FAILIF(elf_hdr.e_type != ET_DYN && - elf_hdr.e_type != ET_EXEC, - "%s must be a shared library or an executable " - "(elf type is %d).\n", - infile, - elf_hdr.e_type); - } - - print_dynamic_symbols(elf, infile); - - FAILIF_LIBELF(elf_end(elf), elf_end); - FAILIF(close(elf_fd) < 0, "Could not close file %s: %s (%d)!\n", - infile, strerror(errno), errno); - } - } - else { - int elf_fd = -1; - Elf *elf = NULL; - infile = argv[first]; - - INFO("Opening %s...\n", infile); - elf_fd = open(infile, ((outfile == NULL && dry_run == 0) ? O_RDWR : O_RDONLY)); - FAILIF(elf_fd < 0, "open(%s): %s (%d)\n", - infile, - strerror(errno), - errno); - INFO("Calling elf_begin(%s)...\n", infile); - elf = elf_begin(elf_fd, - ((outfile == NULL && dry_run == 0) ? ELF_C_RDWR : ELF_C_READ), - NULL); - FAILIF_LIBELF(elf == NULL, elf_begin); - - /* libelf can recognize COFF and A.OUT formats, but we handle only ELF. */ - FAILIF(elf_kind(elf) != ELF_K_ELF, - "Input file %s is not in ELF format!\n", - infile); - - /* We run a better check in adjust_elf() itself. It is permissible to call adjust_elf() - on an executable if we are only stripping sections from the executable, not rearranging - or moving sections. - */ - if (0) { - /* Make sure this is a shared library. */ - GElf_Ehdr elf_hdr; - INFO("Making sure %s is a shared library...\n", infile); - FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr), gelf_getehdr); - FAILIF(elf_hdr.e_type != ET_DYN, - "%s must be a shared library (elf type is %d, expecting %d).\n", - infile, - elf_hdr.e_type, - ET_DYN); - } - - if (outfile != NULL) { - ASSERT(!dry_run); - struct stat st; - FAILIF(fstat (elf_fd, &st) != 0, - "Cannot stat input file %s: %s (%d)!\n", - infile, strerror(errno), errno); - newelf_fd = open (outfile, O_RDWR | O_CREAT | O_TRUNC, - st.st_mode & ACCESSPERMS); - FAILIF(newelf_fd < 0, "Cannot create file %s: %s (%d)!\n", - outfile, strerror(errno), errno); - INFO("Output file is [%s].\n", outfile); - newelf = elf_begin(newelf_fd, ELF_C_WRITE_MMAP, NULL); - } else { - INFO("Modifying [%s] in-place.\n", infile); - newelf = elf_clone(elf, ELF_C_EMPTY); - } - - symfilter_t symfilter; - - symfilter.symbols_to_keep = NULL; - symfilter.num_symbols_to_keep = 0; - if (symsfile_name) { - /* Make sure that the file is not empty. */ - struct stat s; - FAILIF(stat(symsfile_name, &s) < 0, - "Cannot stat file %s.\n", symsfile_name); - if (s.st_size) { - INFO("Building symbol filter.\n"); - build_symfilter(symsfile_name, elf, &symfilter, s.st_size); - } - else INFO("Not building symbol filter, filter file is empty.\n"); - } -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - int prelinked = 0; - int elf_little; /* valid if prelinked != 0 */ - long prelink_addr; /* valid if prelinked != 0 */ -#endif - clone_elf(elf, newelf, - infile, outfile, - symfilter.symbols_to_keep, - symfilter.num_symbols_to_keep, - shady -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - , &prelinked, - &elf_little, - &prelink_addr -#endif - , - true, /* rebuild the section-header-strings table */ - strip_debug, - dry_run); - - if (symsfile_name && symfilter.symbols_to_keep != NULL) { - destroy_symfilter(&symfilter); - } - - if (outfile != NULL) INFO("Closing %s...\n", outfile); - FAILIF_LIBELF(elf_end (newelf) != 0, elf_end); - FAILIF(newelf_fd >= 0 && close(newelf_fd) < 0, - "Could not close file %s: %s (%d)!\n", - outfile, strerror(errno), errno); - - INFO("Closing %s...\n", infile); - FAILIF_LIBELF(elf_end(elf), elf_end); - FAILIF(close(elf_fd) < 0, "Could not close file %s: %s (%d)!\n", - infile, strerror(errno), errno); - -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - if (prelinked) { - INFO("File is prelinked, putting prelink TAG back in place.\n"); - setup_prelink_info(outfile != NULL ? outfile : infile, - elf_little, - prelink_addr); - } -#endif - } - - FREEIF(outfile); - return 0; -} - -static void print_dynamic_symbols(Elf *elf, const char *file) -{ - Elf_Scn *scn = NULL; - GElf_Shdr shdr; - - GElf_Ehdr ehdr; - FAILIF_LIBELF(0 == gelf_getehdr(elf, &ehdr), gelf_getehdr); - while ((scn = elf_nextscn (elf, scn)) != NULL) { - FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr), gelf_getshdr); - if (SHT_DYNSYM == shdr.sh_type) { - /* This failure is too restrictive. There is no reason why - the symbol table couldn't be called something else, but - there is a standard name, and chances are that if we don't - see it, there's something wrong. - */ - size_t shstrndx; - FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0, - elf_getshstrndx); - /* Now print the symbols. */ - { - Elf_Data *symdata; - size_t elsize; - symdata = elf_getdata (scn, NULL); /* get the symbol data */ - FAILIF_LIBELF(NULL == symdata, elf_getdata); - /* Get the number of section. We need to compare agains this - value for symbols that have special info in their section - references */ - size_t shnum; - FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum); - /* Retrieve the size of a symbol entry */ - elsize = gelf_fsize(elf, ELF_T_SYM, 1, ehdr.e_version); - - size_t index; - for (index = 0; index < symdata->d_size / elsize; index++) { - GElf_Sym sym_mem; - GElf_Sym *sym; - /* Get the symbol. */ - sym = gelf_getsymshndx (symdata, NULL, - index, &sym_mem, NULL); - FAILIF_LIBELF(sym == NULL, gelf_getsymshndx); - /* Print the symbol. */ - char bind = '?'; - switch(ELF32_ST_BIND(sym->st_info)) - { - case STB_LOCAL: bind = 'l'; break; - case STB_GLOBAL: bind = 'g'; break; - case STB_WEAK: bind = 'w'; break; - default: break; - } - char type = '?'; - switch(ELF32_ST_TYPE(sym->st_info)) - { - case STT_NOTYPE: /* Symbol type is unspecified */ - type = '?'; - break; - case STT_OBJECT: /* Symbol is a data object */ - type = 'o'; - break; - case STT_FUNC: /* Symbol is a code object */ - type = 'f'; - break; - case STT_SECTION:/* Symbol associated with a section */ - type = 's'; - break; - case STT_FILE: /* Symbol's name is file name */ - type = 'f'; - break; - case STT_COMMON: /* Symbol is a common data object */ - type = 'c'; - break; - case STT_TLS: /* Symbol is thread-local data object*/ - type = 't'; - break; - } - { - int till_lineno; - int lineno; - const char *section_name = "(unknown)"; - FAILIF(sym->st_shndx == SHN_XINDEX, - "Can't handle symbol's st_shndx == SHN_XINDEX!\n"); - if (sym->st_shndx != SHN_UNDEF && - sym->st_shndx < shnum) { - Elf_Scn *symscn = elf_getscn(elf, sym->st_shndx); - FAILIF_LIBELF(NULL == symscn, elf_getscn); - GElf_Shdr symscn_shdr; - FAILIF_LIBELF(NULL == gelf_getshdr(symscn, - &symscn_shdr), - gelf_getshdr); - section_name = elf_strptr(elf, shstrndx, - symscn_shdr.sh_name); - } - else if (sym->st_shndx == SHN_ABS) { - section_name = "SHN_ABS"; - } - else if (sym->st_shndx == SHN_COMMON) { - section_name = "SHN_COMMON"; - } - else if (sym->st_shndx == SHN_UNDEF) { - section_name = "(undefined)"; - } - /* value size binding type section symname */ - PRINT("%-15s %8d: %08llx %08llx %c%c %5d %n%s%n", - file, - index, - sym->st_value, sym->st_size, bind, type, - sym->st_shndx, - &till_lineno, - section_name, - &lineno); - lineno -= till_lineno; - /* Create padding for section names of 15 chars. - This limit is somewhat arbitratry. */ - while (lineno++ < 15) PRINT(" "); - PRINT("(%d) %s\n", - sym->st_name, - elf_strptr(elf, shdr.sh_link, sym->st_name)); - } - } - } - } /* if (shdr.sh_type = SHT_DYNSYM) */ - } /* while ((scn = elf_nextscn (elf, scn)) != NULL) */ -} diff --git a/tools/soslim/prelink_info.c b/tools/soslim/prelink_info.c deleted file mode 100644 index 36516b1..0000000 --- a/tools/soslim/prelink_info.c +++ /dev/null @@ -1,106 +0,0 @@ -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - -#include <sys/types.h> -#include <fcntl.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include <prelink_info.h> -#include <debug.h> -#include <common.h> - -typedef struct { - uint32_t mmap_addr; - char tag[4]; /* 'P', 'R', 'E', ' ' */ -} prelink_info_t __attribute__((packed)); - -static inline void set_prelink(long *prelink_addr, - int elf_little, - prelink_info_t *info) -{ - FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t)); - if (prelink_addr) { - if (!(elf_little ^ is_host_little())) { - /* Same endianness */ - *prelink_addr = info->mmap_addr; - } - else { - /* Different endianness */ - *prelink_addr = switch_endianness(info->mmap_addr); - } - } -} - -int check_prelinked(const char *fname, int elf_little, long *prelink_addr) -{ - FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t)); - int fd = open(fname, O_RDONLY); - FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n", - fname, strerror(errno), errno); - off_t end = lseek(fd, 0, SEEK_END); - - int nr = sizeof(prelink_info_t); - - off_t sz = lseek(fd, -nr, SEEK_CUR); - ASSERT((long)(end - sz) == (long)nr); - FAILIF(sz == (off_t)-1, - "lseek(%d, 0, SEEK_END): %s (%d)!\n", - fd, strerror(errno), errno); - - prelink_info_t info; - int num_read = read(fd, &info, nr); - FAILIF(num_read < 0, - "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n", - fd, strerror(errno), errno); - FAILIF(num_read != sizeof(info), - "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as " - "expected (read %d)!\n", - fd, sizeof(info), num_read); - - int prelinked = 0; - if (!strncmp(info.tag, "PRE ", 4)) { - set_prelink(prelink_addr, elf_little, &info); - prelinked = 1; - } - FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); - return prelinked; -} - -void setup_prelink_info(const char *fname, int elf_little, long base) -{ - FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t)); - int fd = open(fname, O_WRONLY); - FAILIF(fd < 0, - "open(%s, O_WRONLY): %s (%d)\n" , - fname, strerror(errno), errno); - prelink_info_t info; - off_t sz = lseek(fd, 0, SEEK_END); - FAILIF(sz == (off_t)-1, - "lseek(%d, 0, SEEK_END): %s (%d)!\n", - fd, strerror(errno), errno); - - if (!(elf_little ^ is_host_little())) { - /* Same endianness */ - INFO("Host and ELF file [%s] have same endianness.\n", fname); - info.mmap_addr = base; - } - else { - /* Different endianness */ - INFO("Host and ELF file [%s] have different endianness.\n", fname); - info.mmap_addr = switch_endianness(base); - } - strncpy(info.tag, "PRE ", 4); - - int num_written = write(fd, &info, sizeof(info)); - FAILIF(num_written < 0, - "write(%d, &info, sizeof(info)): %s (%d)\n", - fd, strerror(errno), errno); - FAILIF(sizeof(info) != num_written, - "Could not write %d bytes (wrote only %d bytes) as expected!\n", - sizeof(info), num_written); - FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); -} - -#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/ diff --git a/tools/soslim/prelink_info.h b/tools/soslim/prelink_info.h deleted file mode 100644 index e2787cb..0000000 --- a/tools/soslim/prelink_info.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef PRELINK_INFO_H -#define PRELINK_INFO_H -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - -int check_prelinked(const char *fname, int elf_little, long *prelink_addr); -void setup_prelink_info(const char *fname, int elf_little, long base); - -#endif -#endif/*PRELINK_INFO_H*/ diff --git a/tools/soslim/soslim.c b/tools/soslim/soslim.c deleted file mode 100644 index 4e59c24..0000000 --- a/tools/soslim/soslim.c +++ /dev/null @@ -1,528 +0,0 @@ -#include <stdio.h> -//#include <common.h> -#include <debug.h> -#include <libelf.h> -#include <libebl.h> -#include <libebl_arm.h> -#include <elf.h> -#include <gelf.h> -#include <string.h> -#include <errno.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#ifdef SUPPORT_ANDROID_PRELINK_TAGS -#include <prelink_info.h> -#endif - -#include <elfcopy.h> - -void clone_elf(Elf *elf, Elf *newelf, - const char *elf_name, - const char *newelf_name, - bool *sym_filter, int num_symbols, - int shady -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - , int *prelinked, - int *elf_little, - long *prelink_addr -#endif - , bool rebuild_shstrtab, - bool strip_debug, - bool dry_run) -{ - GElf_Ehdr ehdr_mem, *ehdr; /* store ELF header of original library */ - size_t shstrndx; /* section-strings-section index */ - size_t shnum; /* number of sections in the original file */ - /* string table for section headers in new file */ - struct Ebl_Strtab *shst = NULL; - int dynamic_idx = -1; /* index in shdr_info[] of .dynamic section */ - int dynsym_idx = -1; /* index in shdr_info[] of dynamic symbol table - section */ - - int cnt; /* general-purpose counter */ - /* This flag is true when at least one section is dropped or when the - relative order of sections has changed, so that section indices in - the resulting file will be different from those in the original. */ - bool sections_dropped_or_rearranged; - Elf_Scn *scn; /* general-purpose section */ - size_t idx; /* general-purporse section index */ - - shdr_info_t *shdr_info = NULL; - int shdr_info_len = 0; - GElf_Phdr *phdr_info = NULL; - - /* Get the information from the old file. */ - ehdr = gelf_getehdr (elf, &ehdr_mem); - FAILIF_LIBELF(NULL == ehdr, gelf_getehdr); - - /* Create new program header for the elf file */ - FAILIF(gelf_newehdr (newelf, gelf_getclass (elf)) == 0 || - (ehdr->e_type != ET_REL && gelf_newphdr (newelf, - ehdr->e_phnum) == 0), - "Cannot create new file: %s", elf_errmsg (-1)); - -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - ASSERT(prelinked); - ASSERT(prelink_addr); - ASSERT(elf_little); - *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB); - *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr); -#endif - - INFO("\n\nCALCULATING MODIFICATIONS\n\n"); - - /* Copy out the old program header: notice that if the ELF file does not - have a program header, this loop won't execute. - */ - INFO("Copying ELF program header...\n"); - phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum, sizeof(GElf_Phdr)); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) { - INFO("\tRetrieving entry %d\n", cnt); - FAILIF_LIBELF(NULL == gelf_getphdr(elf, cnt, phdr_info + cnt), - gelf_getphdr); - /* -- we update the header at the end - FAILIF_LIBELF(gelf_update_phdr (newelf, cnt, phdr_info + cnt) == 0, - gelf_update_phdr); - */ - } - - /* Get the section-header strings section. This section contains the - strings used to name the other sections. */ - FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0, elf_getshstrndx); - - /* Get the number of sections. */ - FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum); - INFO("Original ELF file has %d sections.\n", shnum); - - /* Allocate the section-header-info buffer. We allocate one more entry - for the section-strings section because we regenerate that one and - place it at the very end of the file. Note that just because we create - an extra entry in the shdr_info array, it does not mean that we create - one more section the header. We just mark the old section for removal - and create one as the last section. - */ - INFO("Allocating section-header info structure (%d) bytes...\n", - shnum*sizeof (shdr_info_t)); - shdr_info_len = rebuild_shstrtab ? shnum + 1 : shnum; - shdr_info = (shdr_info_t *)CALLOC(shdr_info_len, sizeof (shdr_info_t)); - - /* Iterate over all the sections and initialize the internal section-info - array... - */ - INFO("Initializing section-header info structure...\n"); - /* Gather information about the sections in this file. */ - scn = NULL; - cnt = 1; - while ((scn = elf_nextscn (elf, scn)) != NULL) { - ASSERT(elf_ndxscn(scn) == cnt); - shdr_info[cnt].scn = scn; - FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr_info[cnt].shdr), - gelf_getshdr); - - /* Get the name of the section. */ - shdr_info[cnt].name = elf_strptr (elf, shstrndx, - shdr_info[cnt].shdr.sh_name); - - INFO("\tname: %s\n", shdr_info[cnt].name); - FAILIF(shdr_info[cnt].name == NULL, - "Malformed file: section %d name is null\n", - cnt); - - /* Mark them as present but not yet investigated. By "investigating" - sections, we mean that we check to see if by stripping other - sections, the sections under investigation will be compromised. For - example, if we are removing a section of code, then we want to make - sure that the symbol table does not contain symbols that refer to - this code, so we investigate the symbol table. If we do find such - symbols, we will not strip the code section. - */ - shdr_info[cnt].idx = 1; - - /* Remember the shdr.sh_link value. We need to remember this value - for those sections that refer to other sections. For example, - we need to remember it for relocation-entry sections, because if - we modify the symbol table that a relocation-entry section is - relative to, then we need to patch the relocation section. By the - time we get to deciding whether we need to patch the relocation - section, we will have overwritten its header's sh_link field with - a new value. - */ - shdr_info[cnt].old_shdr = shdr_info[cnt].shdr; - INFO("\t\toriginal sh_link: %08d\n", shdr_info[cnt].old_shdr.sh_link); - INFO("\t\toriginal sh_addr: %lld\n", shdr_info[cnt].old_shdr.sh_addr); - INFO("\t\toriginal sh_offset: %lld\n", - shdr_info[cnt].old_shdr.sh_offset); - INFO("\t\toriginal sh_size: %lld\n", shdr_info[cnt].old_shdr.sh_size); - - if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) { - INFO("\t\tthis is the SHT_DYNAMIC section [%s] at index %d\n", - shdr_info[cnt].name, - cnt); - dynamic_idx = cnt; - } - else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) { - INFO("\t\tthis is the SHT_DYNSYM section [%s] at index %d\n", - shdr_info[cnt].name, - cnt); - dynsym_idx = cnt; - } - - FAILIF(shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX, - "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n"); - FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP, - "Cannot handle sh_type SHT_GROUP!\n"); - FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym, - "Cannot handle sh_type SHT_GNU_versym!\n"); - - /* Increment the counter. */ - ++cnt; - } /* while */ - - /* Get the EBL handling. */ - Ebl *ebl = ebl_openbackend (elf); - FAILIF_LIBELF(NULL == ebl, ebl_openbackend); - FAILIF_LIBELF(0 != arm_init(elf, ehdr->e_machine, ebl, sizeof(Ebl)), - arm_init); - - if (strip_debug) { - - /* This will actually strip more than just sections. It will strip - anything not essential to running the image. - */ - - INFO("Finding debug sections to strip.\n"); - - /* Now determine which sections can go away. The general rule is that - all sections which are not used at runtime are stripped out. But - there are a few exceptions: - - - special sections named ".comment" and ".note" are kept - - OS or architecture specific sections are kept since we might not - know how to handle them - - if a section is referred to from a section which is not removed - in the sh_link or sh_info element it cannot be removed either - */ - for (cnt = 1; cnt < shnum; ++cnt) { - /* Check whether the section can be removed. */ - if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr, - shdr_info[cnt].name, - 1, /* remove .comment sections */ - 1 /* remove all debug sections */) || - /* The macro above is broken--check for .comment explicitly */ - !strcmp(".comment", shdr_info[cnt].name) -#ifdef ARM_SPECIFIC_HACKS - || - /* We ignore this section, that's why we can remove it. */ - !strcmp(".stack", shdr_info[cnt].name) -#endif - ) - { - /* For now assume this section will be removed. */ - INFO("Section [%s] will be stripped from image.\n", - shdr_info[cnt].name); - shdr_info[cnt].idx = 0; - } -#ifdef STRIP_STATIC_SYMBOLS - else if (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB) { - /* Mark the static symbol table for removal */ - INFO("Section [%s] (static symbol table) will be stripped from image.\n", - shdr_info[cnt].name); - shdr_info[cnt].idx = 0; - if (shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type == - SHT_STRTAB) - { - /* Mark the symbol table's string table for removal. */ - INFO("Section [%s] (static symbol-string table) will be stripped from image.\n", - shdr_info[cnt].name); - shdr_info[shdr_info[cnt].shdr.sh_link].idx = 0; - } - else { - ERROR("Expecting the sh_link field of a symbol table to point to" - " associated symbol-strings table! This is not mandated by" - " the standard, but is a common practice and the only way " - " to know for sure which strings table corresponds to which" - " symbol table!\n"); - } - } -#endif - } - - /* Mark the SHT_NULL section as handled. */ - shdr_info[0].idx = 2; - - /* Handle exceptions: section groups and cross-references. We might have - to repeat this a few times since the resetting of the flag might - propagate. - */ - int exceptions_pass = 0; - bool changes; - do { - changes = false; - INFO("\nHandling exceptions, pass %d\n\n", exceptions_pass++); - for (cnt = 1; cnt < shnum; ++cnt) { - if (shdr_info[cnt].idx == 0) { - /* If a relocation section is marked as being removed but the - section it is relocating is not, then do not remove the - relocation section. - */ - if ((shdr_info[cnt].shdr.sh_type == SHT_REL - || shdr_info[cnt].shdr.sh_type == SHT_RELA) - && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) { - PRINT("\tSection [%s] will not be removed because the " - "section it is relocating (%s) stays.\n", - shdr_info[cnt].name, - shdr_info[shdr_info[cnt].shdr.sh_info].name); - } - } - if (shdr_info[cnt].idx == 1) { - INFO("Processing section [%s]...\n", shdr_info[cnt].name); - - /* The content of symbol tables we don't remove must not - reference any section which we do remove. Otherwise - we cannot remove the referred section. - */ - if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM || - shdr_info[cnt].shdr.sh_type == SHT_SYMTAB) - { - Elf_Data *symdata; - size_t elsize; - - INFO("\tSection [%s] is a symbol table that's not being" - " removed.\n\tChecking to make sure that no symbols" - " refer to sections that are being removed.\n", - shdr_info[cnt].name); - - /* Make sure the data is loaded. */ - symdata = elf_getdata (shdr_info[cnt].scn, NULL); - FAILIF_LIBELF(NULL == symdata, elf_getdata); - - /* Go through all symbols and make sure the section they - reference is not removed. */ - elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version); - - /* Check the length of the dynamic-symbol filter. */ - FAILIF(sym_filter != NULL && - num_symbols != symdata->d_size / elsize, - "Length of dynsym filter (%d) must equal the number" - " of dynamic symbols (%d)!\n", - num_symbols, - symdata->d_size / elsize); - - size_t inner; - for (inner = 0; - inner < symdata->d_size / elsize; - ++inner) - { - GElf_Sym sym_mem; - GElf_Sym *sym; - size_t scnidx; - - sym = gelf_getsymshndx (symdata, NULL, - inner, &sym_mem, NULL); - FAILIF_LIBELF(sym == NULL, gelf_getsymshndx); - - scnidx = sym->st_shndx; - FAILIF(scnidx == SHN_XINDEX, - "Can't handle SHN_XINDEX!\n"); - if (scnidx == SHN_UNDEF || - scnidx >= shnum || - (scnidx >= SHN_LORESERVE && - scnidx <= SHN_HIRESERVE) || - GELF_ST_TYPE (sym->st_info) == STT_SECTION) - { - continue; - } - - /* If the symbol is going to be thrown and it is a - global or weak symbol that is defined (not imported), - then continue. Since the symbol is going away, we - do not care whether it refers to a section that is - also going away. - */ - if (sym_filter && !sym_filter[inner]) - { - bool global_or_weak = - ELF32_ST_BIND(sym->st_info) == STB_GLOBAL || - ELF32_ST_BIND(sym->st_info) == STB_WEAK; - if (!global_or_weak && sym->st_shndx != SHN_UNDEF) - continue; - } - - /* -- far too much output - INFO("\t\t\tSymbol [%s] (%d)\n", - elf_strptr(elf, - shdr_info[cnt].shdr.sh_link, - sym->st_name), - shdr_info[cnt].shdr.sh_info); - */ - - if (shdr_info[scnidx].idx == 0) - { - PRINT("\t\t\tSymbol [%s] refers to section [%s], " - "which is being removed. Will keep that " - "section.\n", - elf_strptr(elf, - shdr_info[cnt].shdr.sh_link, - sym->st_name), - shdr_info[scnidx].name); - /* Mark this section as used. */ - shdr_info[scnidx].idx = 1; - changes |= scnidx < cnt; - } - } /* for each symbol */ - } /* section type is SHT_DYNSYM or SHT_SYMTAB */ - /* Cross referencing happens: - - for the cases the ELF specification says. That are - + SHT_DYNAMIC in sh_link to string table - + SHT_HASH in sh_link to symbol table - + SHT_REL and SHT_RELA in sh_link to symbol table - + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table - + SHT_GROUP in sh_link to symbol table - + SHT_SYMTAB_SHNDX in sh_link to symbol table - Other (OS or architecture-specific) sections might as - well use this field so we process it unconditionally. - - references inside section groups - - specially marked references in sh_info if the SHF_INFO_LINK - flag is set - */ - - if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0) { - shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1; - changes |= shdr_info[cnt].shdr.sh_link < cnt; - } - - /* Handle references through sh_info. */ - if (SH_INFO_LINK_P (&shdr_info[cnt].shdr) && - shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) { - PRINT("\tSection [%s] links to section [%s], which was " - "marked for removal--it will not be removed.\n", - shdr_info[cnt].name, - shdr_info[shdr_info[cnt].shdr.sh_info].name); - - shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1; - changes |= shdr_info[cnt].shdr.sh_info < cnt; - } - - /* Mark the section as investigated. */ - shdr_info[cnt].idx = 2; - } /* if (shdr_info[cnt].idx == 1) */ - } /* for (cnt = 1; cnt < shnum; ++cnt) */ - } while (changes); - } - else { - INFO("Not stripping sections.\n"); - /* Mark the SHT_NULL section as handled. */ - shdr_info[0].idx = 2; - } - - /* Mark the section header string table as unused, we will create - a new one as the very last section in the new ELF file. - */ - shdr_info[shstrndx].idx = rebuild_shstrtab ? 0 : 2; - - /* We need a string table for the section headers. */ - FAILIF_LIBELF((shst = ebl_strtabinit (1 /* null-terminated */)) == NULL, - ebl_strtabinit); - - /* Assign new section numbers. */ - INFO("Creating new sections...\n"); - //shdr_info[0].idx = 0; - for (cnt = idx = 1; cnt < shnum; ++cnt) { - if (shdr_info[cnt].idx > 0) { - shdr_info[cnt].idx = idx++; - - /* Create a new section. */ - FAILIF_LIBELF((shdr_info[cnt].newscn = - elf_newscn(newelf)) == NULL, elf_newscn); - ASSERT(elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx); - - /* Add this name to the section header string table. */ - shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0); - - INFO("\tsection [%s] (old offset %lld, old size %lld) will have index %d " - "(was %d).\n", - shdr_info[cnt].name, - shdr_info[cnt].old_shdr.sh_offset, - shdr_info[cnt].old_shdr.sh_size, - shdr_info[cnt].idx, - elf_ndxscn(shdr_info[cnt].scn)); - } else { - INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %d), " - "it will be discarded.\n", - shdr_info[cnt].name, - shdr_info[cnt].shdr.sh_offset, - shdr_info[cnt].shdr.sh_size, - elf_ndxscn(shdr_info[cnt].scn)); - } - } /* for */ - - sections_dropped_or_rearranged = idx != cnt; - - Elf_Data *shstrtab_data = NULL; - -#if 0 - /* Fail if sections are being dropped or rearranged (except for moving shstrtab) or the - symbol filter is not empty, AND the file is an executable. - */ - FAILIF(((idx != cnt && !(cnt - idx == 1 && rebuild_shstrtab)) || sym_filter != NULL) && - ehdr->e_type != ET_DYN, - "You may not rearrange sections or strip symbols on an executable file!\n"); -#endif - - INFO("\n\nADJUSTING ELF FILE\n\n"); - - adjust_elf(elf, elf_name, - newelf, newelf_name, - ebl, - ehdr, /* store ELF header of original library */ - sym_filter, num_symbols, - shdr_info, shdr_info_len, - phdr_info, - idx, /* highest_scn_num */ - shnum, - shstrndx, - shst, - sections_dropped_or_rearranged, - dynamic_idx, /* index in shdr_info[] of .dynamic section */ - dynsym_idx, /* index in shdr_info[] of dynamic symbol table */ - shady, - &shstrtab_data, - ehdr->e_type == ET_DYN, /* adjust section ofsets only when the file is a shared library */ - rebuild_shstrtab); - - /* We have everything from the old file. */ - FAILIF_LIBELF(elf_cntl(elf, ELF_C_FDDONE) != 0, elf_cntl); - - /* The ELF library better follows our layout when this is not a - relocatable object file. */ - elf_flagelf (newelf, - ELF_C_SET, - (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)); - - /* Finally write the file. */ - FAILIF_LIBELF(!dry_run && elf_update(newelf, ELF_C_WRITE) == -1, elf_update); - - if (shdr_info != NULL) { - /* For some sections we might have created an table to map symbol - table indices. */ - for (cnt = 1; cnt < shdr_info_len; ++cnt) { - FREEIF(shdr_info[cnt].newsymidx); - FREEIF(shdr_info[cnt].symse); - if(shdr_info[cnt].dynsymst != NULL) - ebl_strtabfree (shdr_info[cnt].dynsymst); - } - /* Free the memory. */ - FREE (shdr_info); - } - FREEIF(phdr_info); - - ebl_closebackend(ebl); - - /* Free other resources. */ - if (shst != NULL) ebl_strtabfree (shst); - if (shstrtab_data != NULL) - FREEIF(shstrtab_data->d_buf); -} diff --git a/tools/soslim/soslim.h b/tools/soslim/soslim.h deleted file mode 100644 index dfcb085..0000000 --- a/tools/soslim/soslim.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ELFCOPY_H -#define ELFCOPY_H - -#include <libelf.h> -#include <libebl.h> -#include <elf.h> -#include <gelf.h> - -/* -symbol_filter: - On input: symbol_filter[i] indicates whether to keep a symbol (1) or to - remove it from the symbol table. - On output: symbol_filter[i] indicates whether a symbol was removed (0) or - kept (1) in the symbol table. -*/ - -void clone_elf(Elf *elf, Elf *newelf, - const char *elf_name, - const char *newelf_name, - bool *symbol_filter, - int num_symbols, - int shady -#ifdef SUPPORT_ANDROID_PRELINK_TAGS - , int *prelinked, - int *elf_little, - long *prelink_addr -#endif - , bool rebuild_shstrtab, - bool strip_debug, - bool dry_run); - -#endif/*ELFCOPY_H*/ diff --git a/tools/soslim/symfilter.c b/tools/soslim/symfilter.c deleted file mode 100644 index c21ab2e..0000000 --- a/tools/soslim/symfilter.c +++ /dev/null @@ -1,242 +0,0 @@ -#include <debug.h> -#include <common.h> -#include <symfilter.h> -#include <hash.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <libelf.h> -#include <gelf.h> -#include <ctype.h> - -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -static int match_hash_table_section(Elf *elf, Elf_Scn *sect, void *data); -static int match_dynsym_section(Elf *elf, Elf_Scn *sect, void *data); - -void build_symfilter(const char *name, Elf *elf, symfilter_t *filter, - off_t fsize) -{ - char *line = NULL; - symfilter_list_t *symbol; - - FAILIF(NULL == name, - "You must provide a list of symbols to filter on!\n"); - - filter->num_symbols = 0; - filter->total_name_length = 0; - - /* Open the file. */ - INFO("Opening symbol-filter file %s...\n", name); - filter->fd = open(name, O_RDONLY); - FAILIF(filter->fd < 0, "open(%s): %s (%d)\n", - name, - strerror(errno), - errno); - - INFO("Symbol-filter file %s is %ld bytes long...\n", - name, - fsize); - filter->fsize = fsize; - - /* mmap the symbols file */ - filter->mmap = mmap(NULL, fsize, - PROT_READ | PROT_WRITE, MAP_PRIVATE, - filter->fd, 0); - FAILIF(MAP_FAILED == filter->mmap, - "mmap(NULL, %ld, PROT_READ, MAP_PRIVATE, %d, 0): %s (%d)\n", - fsize, - filter->fd, - strerror(errno), - errno); - INFO("Memory-mapped symbol-filter file at %p\n", filter->mmap); - - /* Make sure that the ELF file has a hash table. We will use the hash - table to look up symbols quickly. If the library does not have a hash- - table section, we can still do a linear scan, but the code for that is - not written, as practically every shared library has a hash table. - */ - - filter->symtab.sect = NULL; - map_over_sections(elf, match_dynsym_section, filter); - FAILIF(NULL == filter->symtab.sect, - "There is no dynamic-symbol table in this library.\n"); - filter->hash.sect = NULL; - map_over_sections(elf, match_hash_table_section, filter); - FAILIF(NULL == filter->hash.sect, - "There is no hash table in this library.\n"); - INFO("Hash table size 0x%lx, data size 0x%lx.\n", - (unsigned long)filter->hash.hdr->sh_size, - (unsigned long)filter->hash.data->d_size); - - INFO("Hash table file offset: 0x%x\n", filter->hash.hdr->sh_offset); - - GElf_Ehdr *ehdr, ehdr_mem; - ehdr = gelf_getehdr(elf, &ehdr_mem); - size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version); - ASSERT(symsize); - filter->num_symbols_to_keep = filter->symtab.data->d_size / symsize; - filter->symbols_to_keep = (bool *)CALLOC(filter->num_symbols_to_keep, - sizeof(bool)); - - /* Build the symbol-name chain. */ - INFO("Building symbol list...\n"); - - line = (char *)filter->mmap; - - filter->symbols = NULL; -#define NOT_DONE ((off_t)(line - (char *)filter->mmap) < fsize) - do { - char *name = line; - - /* Advance to the next line. We seek out spaces or new lines. At the - first space or newline character we find, we place a '\0', and - continue till we've consumed the line. For new lines, we scan both - '\r' and '\n'. For spaces, we look for ' ', '\t', and '\f' - */ - - while (NOT_DONE && !isspace(*line)) line++; - if (likely(NOT_DONE)) { - *line++ = '\0'; - if (line - name > 1) { - /* Add the entry to the symbol-filter list */ - symbol = (symfilter_list_t *)MALLOC(sizeof(symfilter_list_t)); - symbol->next = filter->symbols; - symbol->name = name; - filter->symbols = symbol; - -#if 0 - /* SLOW! For debugging only! */ - { - size_t idx; - size_t elsize = gelf_fsize(elf, ELF_T_SYM, 1, - ehdr->e_version); - symbol->index = SHN_UNDEF; - for (idx = 0; idx < filter->symtab.data->d_size / elsize; - idx++) { - GElf_Sym sym_mem; - GElf_Sym *sym; - const char *symname; - sym = gelf_getsymshndx (filter->symtab.data, NULL, - idx, &sym_mem, NULL); - ASSERT(sym); - - symname = elf_strptr(elf, - filter->symtab.hdr->sh_link, - sym->st_name); - if(!strcmp(symname, symbol->name)) { - symbol->index = idx; - break; - } - } - } -#else - /* Look up the symbol in the ELF file and associate it with the - entry in the filter. */ - symbol->index = hash_lookup(elf, - &filter->hash, - &filter->symtab, - symbol->name, - &symbol->symbol); -#endif - symbol->len = line - name - 1; - ASSERT(symbol->len == strlen(symbol->name)); - - /* If we didn't find the symbol, then it's not in the library. - */ - - if(STN_UNDEF == symbol->index) { - PRINT("%s: symbol was not found!\n", symbol->name); - } - else { - /* If we found the symbol but it's an undefined symbol, then - it's not in the library as well. */ - GElf_Sym sym_mem; - GElf_Sym *sym; - sym = gelf_getsymshndx (filter->symtab.data, NULL, - symbol->index, &sym_mem, NULL); - FAILIF_LIBELF(NULL == sym, gelf_getsymshndx); - /* Make sure the hash lookup worked. */ - ASSERT(!strcmp(elf_strptr(elf, - filter->symtab.hdr->sh_link, - sym->st_name), - symbol->name)); - if (sym->st_shndx == SHN_UNDEF) { - PRINT("%s: symbol was not found (undefined)!\n", symbol->name); - } - else { - filter->num_symbols++; - /* Total count includes null terminators */ - filter->total_name_length += symbol->len + 1; - - /* Set the flag in the symbols_to_keep[] array. This indicates - to function copy_elf() that we want to keep the symbol. - */ - filter->symbols_to_keep[symbol->index] = true; - INFO("FILTER-SYMBOL: [%s] [%d bytes]\n", - symbol->name, - symbol->len); - } - } - } - } - } while (NOT_DONE); -#undef NOT_DONE -} - -void destroy_symfilter(symfilter_t *filter) -{ - symfilter_list_t *old; - INFO("Destroying symbol list...\n"); - while ((old = filter->symbols)) { - filter->symbols = old->next; - FREE(old); - } - munmap(filter->mmap, filter->fsize); - close(filter->fd); -} - -static int match_hash_table_section(Elf *elf, Elf_Scn *sect, void *data) -{ - symfilter_t *filter = (symfilter_t *)data; - Elf32_Shdr *shdr; - - ASSERT(filter); - ASSERT(sect); - shdr = elf32_getshdr(sect); - - /* The section must be marked both as a SHT_HASH, and it's sh_link field - must contain the index of our symbol table (per ELF-file spec). - */ - if (shdr->sh_type == SHT_HASH) - { - FAILIF(filter->hash.sect != NULL, - "There is more than one hash table!\n"); - get_section_info(sect, &filter->hash); - } - - return 0; /* keep looking */ -} - -static int match_dynsym_section(Elf *elf, Elf_Scn *sect, void *data) -{ - symfilter_t *filter = (symfilter_t *)data; - Elf32_Shdr *shdr; - - ASSERT(filter); - ASSERT(sect); - shdr = elf32_getshdr(sect); - - if (shdr->sh_type == SHT_DYNSYM) - { - FAILIF(filter->symtab.sect != NULL, - "There is more than one dynamic symbol table!\n"); - get_section_info(sect, &filter->symtab); - } - - return 0; /* keep looking */ -} diff --git a/tools/soslim/symfilter.h b/tools/soslim/symfilter.h deleted file mode 100644 index f73fd50..0000000 --- a/tools/soslim/symfilter.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef SYMFILTER_H -#define SYMFILTER_H - -/* This file describes the interface for parsing the list of symbols. Currently, - this is just a text file with each symbol on a separate line. We build an - in-memory linked list of symbols out of this image. -*/ - -#include <stdio.h> -#include <libelf.h> -#include <gelf.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <libebl.h> /* defines bool */ - -typedef struct symfilter_list_t symfilter_list_t; -struct symfilter_list_t { - symfilter_list_t *next; - const char *name; - unsigned int len; /* strlen(name) */ - Elf32_Word index; - GElf_Sym symbol; -}; - -typedef struct symfilter_t { - - int fd; /* symbol-filter-file descriptor */ - off_t fsize; /* size of file */ - void *mmap; /* symbol-fiter-file memory mapping */ - - section_info_t symtab; - section_info_t hash; - symfilter_list_t *symbols; - - /* The total number of symbols in the symfilter. */ - unsigned int num_symbols; - /* The total number of bytes occupied by the names of the symbols, including - the terminating null characters. - */ - unsigned int total_name_length; - - bool *symbols_to_keep; - /* must be the same as the number of symbols in the dynamic table! */ - int num_symbols_to_keep; -} symfilter_t; - -void build_symfilter(const char *name, Elf *elf, symfilter_t *filter, off_t); -void destroy_symfilter(symfilter_t *); - -#endif/*SYMFILTER_H*/ |