summaryrefslogtreecommitdiffstats
path: root/tools/soslim/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/soslim/main.c')
-rw-r--r--tools/soslim/main.c360
1 files changed, 0 insertions, 360 deletions
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) */
-}