diff options
author | Iliyan Malchev <malchev@google.com> | 2011-03-08 16:19:48 -0800 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-03-12 14:59:46 -0800 |
commit | b375e71d306f2fd356b9b356b636e568c4581fa1 (patch) | |
tree | 0cb0325afabe55732edb092659793d39d51c4212 /tools/soslim | |
parent | 0469678719a5e8d59b779c8ae8e87a317c5788f5 (diff) | |
download | build-b375e71d306f2fd356b9b356b636e568c4581fa1.tar.gz build-b375e71d306f2fd356b9b356b636e568c4581fa1.tar.bz2 build-b375e71d306f2fd356b9b356b636e568c4581fa1.zip |
build: remove prelinker build build system
This patch removes support for prelinking from the build system. By now, the
prelinker has outlived its usefulness for several reasons. Firstly, the
speedup that it afforded in the early days of Android is now nullified by the
speed of hardware, as well as by the presence of Zygote. Secondly, the space
savings that come with prelinking (measued at 17MB on a recent honeycomb
stingray build) are no longer important either. Thirdly, prelinking reduces
the effectiveness of Address-Space-Layout Randomization. Finally, since it is
not part of the gcc suite, the prelinker needs to be maintained separately.
The patch deletes apriori, soslim, lsd, isprelinked, and iself from the source
tree. It also removes the prelink map.
LOCAL_PRELINK_MODULE becomes a no-op. Individual Android.mk will get cleaned
separately. Support for prelinking will have to be removed from the recovery
code and from the dynamic loader as well.
Change-Id: I5839c9c25f7772d5183eedfe20ab924f2a7cd411
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 | 374 | ||||
-rw-r--r-- | tools/soslim/prelink_info.c | 204 | ||||
-rw-r--r-- | tools/soslim/prelink_info.h | 13 | ||||
-rw-r--r-- | tools/soslim/soslim.c | 536 | ||||
-rw-r--r-- | tools/soslim/soslim.h | 35 | ||||
-rw-r--r-- | tools/soslim/symfilter.c | 246 | ||||
-rw-r--r-- | tools/soslim/symfilter.h | 50 |
14 files changed, 0 insertions, 1876 deletions
diff --git a/tools/soslim/Android.mk b/tools/soslim/Android.mk deleted file mode 100644 index 60a860a28..000000000 --- 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 c2d5e7176..000000000 --- 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 bfc431ee2..000000000 --- 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 b90cf4199..000000000 --- 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 dacf930c6..000000000 --- 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 b8365af4e..000000000 --- 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 e7a2f9a00..000000000 --- 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 df4848427..000000000 --- a/tools/soslim/main.c +++ /dev/null @@ -1,374 +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, retouched = 0; - int elf_little; /* valid if prelinked != 0 */ - long prelink_addr; /* valid if prelinked != 0 */ -#define RETOUCH_MAX_SIZE 600000 - /* _cnt valid if retouched != 0 */ - unsigned int retouch_byte_cnt = RETOUCH_MAX_SIZE; - char retouch_buf[RETOUCH_MAX_SIZE]; /* valid if retouched != 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, - &retouched, - &retouch_byte_cnt, - retouch_buf -#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 (retouched) { - INFO("File has retouch data, putting it back in place.\n"); - retouch_dump(outfile != NULL ? outfile : infile, - elf_little, - retouch_byte_cnt, - retouch_buf); - } - 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 %8zd: %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 2600ac73b..000000000 --- a/tools/soslim/prelink_info.c +++ /dev/null @@ -1,204 +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> - -#define RETOUCH_SUFFIX_SIZE 12 -typedef struct { - uint32_t mmap_addr; - char tag[4]; /* 'P', 'R', 'E', ' ' */ -} __attribute__((packed)) prelink_info_t; - -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) == %zd!\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) == %zd!\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); -#ifndef DEBUG - (void)end; -#endif - - 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; - ssize_t 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((size_t)num_read != sizeof(info), - "read(%d, &info, sizeof(prelink_info_t)): did not read %zd bytes as " - "expected (read %zd)!\n", - fd, sizeof(info), (size_t)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; -} - -int check_retouched(const char *fname, int elf_little, - unsigned int *retouch_byte_cnt, char *retouch_buf) { - 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-RETOUCH_SUFFIX_SIZE, SEEK_CUR); - ASSERT((long)(end - sz) == (long)(nr+RETOUCH_SUFFIX_SIZE)); - FAILIF(sz == (off_t)-1, - "lseek(%d, 0, SEEK_END): %s (%d)!\n", - fd, strerror(errno), errno); - - char retouch_meta[RETOUCH_SUFFIX_SIZE]; - int num_read = read(fd, &retouch_meta, RETOUCH_SUFFIX_SIZE); - FAILIF(num_read < 0, - "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n", - fd, strerror(errno), errno); - FAILIF(num_read != RETOUCH_SUFFIX_SIZE, - "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as " - "expected (read %d)!\n", - fd, RETOUCH_SUFFIX_SIZE, num_read); - - int retouched = 0; - if (!strncmp(retouch_meta, "RETOUCH ", 8)) { - unsigned int retouch_byte_cnt_meta; - if (!(elf_little ^ is_host_little())) - retouch_byte_cnt_meta = *(unsigned int *)(retouch_meta+8); - else - retouch_byte_cnt_meta = - switch_endianness(*(unsigned int *)(retouch_meta+8)); - FAILIF(*retouch_byte_cnt < retouch_byte_cnt_meta, - "Retouch buffer too small at %d bytes (%d needed).", - *retouch_byte_cnt, retouch_byte_cnt_meta); - *retouch_byte_cnt = retouch_byte_cnt_meta; - off_t sz = lseek(fd, - -((long)*retouch_byte_cnt)-RETOUCH_SUFFIX_SIZE-nr, - SEEK_END); - ASSERT((long)(end - sz) == - (long)(*retouch_byte_cnt+RETOUCH_SUFFIX_SIZE+nr)); - FAILIF(sz == (off_t)-1, - "lseek(%d, 0, SEEK_END): %s (%d)!\n", - fd, strerror(errno), errno); - num_read = read(fd, retouch_buf, *retouch_byte_cnt); - FAILIF(num_read < 0, - "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n", - fd, strerror(errno), errno); - FAILIF(num_read != *retouch_byte_cnt, - "read(%d, retouch_buf, %u): did not read %d bytes as " - "expected (read %d)!\n", - fd, *retouch_byte_cnt, *retouch_byte_cnt, num_read); - - retouched = 1; - } - FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); - return retouched; -} - -void retouch_dump(const char *fname, int elf_little, - unsigned int retouch_byte_cnt, char *retouch_buf) { - int fd = open(fname, O_WRONLY); - FAILIF(fd < 0, - "open(%s, O_WRONLY): %s (%d)\n", - fname, strerror(errno), errno); - 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); - - // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte - // size of the retouch blob, in target endianness. - strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8); - if (elf_little ^ is_host_little()) { - *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) = - switch_endianness(retouch_byte_cnt); - } else { - *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) = - retouch_byte_cnt; - } - - int num_written = write(fd, retouch_buf, retouch_byte_cnt+12); - FAILIF(num_written < 0, - "write(%d, &info, sizeof(info)): %s (%d)\n", - fd, strerror(errno), errno); - FAILIF((retouch_byte_cnt+12) != num_written, - "Could not write %d bytes as expected (wrote %d bytes instead)!\n", - retouch_byte_cnt, num_written); - FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno); -} - -void setup_prelink_info(const char *fname, int elf_little, long base) -{ - FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\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); - - ssize_t 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) != (size_t)num_written, - "Could not write %zd bytes (wrote only %zd bytes) as expected!\n", - sizeof(info), (size_t)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 efa84fdab..000000000 --- a/tools/soslim/prelink_info.h +++ /dev/null @@ -1,13 +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); -int check_retouched(const char *fname, int elf_little, - unsigned int *retouch_byte_cnt, char *retouch_buf); -void retouch_dump(const char *fname, int elf_little, - unsigned int retouch_byte_cnt, char *retouch_buf); -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 33b1ee700..000000000 --- a/tools/soslim/soslim.c +++ /dev/null @@ -1,536 +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, - int *retouched, - unsigned int *retouch_byte_cnt, - char *retouch_buf -#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 */ - - unsigned 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; - unsigned 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); - ASSERT(retouched); - ASSERT(retouch_byte_cnt); - ASSERT(retouch_buf); - *retouched = check_retouched(elf_name, *elf_little, - retouch_byte_cnt, retouch_buf); -#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 %zd 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 (%zd) 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[shdr_info[cnt].shdr.sh_link].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 && - (size_t)num_symbols != symdata->d_size / elsize, - "Length of dynsym filter (%d) must equal the number" - " of dynamic symbols (%zd)!\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 %zd).\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 %zd), " - "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 952c960f3..000000000 --- a/tools/soslim/soslim.h +++ /dev/null @@ -1,35 +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, - int *retouched, - unsigned int *retouch_byte_cnt, - char *retouch_buf -#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 b59e68a03..000000000 --- a/tools/soslim/symfilter.c +++ /dev/null @@ -1,246 +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 %zd bytes long...\n", - name, - (size_t)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, %zd, PROT_READ, MAP_PRIVATE, %d, 0): %s (%d)\n", - (size_t)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) -{ - (void)elf; // unused argument - - 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) -{ - (void)elf; // unused argument - - 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 f73fd506c..000000000 --- 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*/ |