readsoname2.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. static char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
  2. {
  3. ElfW(Ehdr) *epnt;
  4. ElfW(Phdr) *ppnt;
  5. unsigned int i, j;
  6. char *header;
  7. ElfW(Addr) dynamic_addr = 0;
  8. ElfW(Addr) dynamic_size = 0;
  9. unsigned long page_size = getpagesize();
  10. ElfW(Addr) strtab_val = 0;
  11. ElfW(Addr) needed_val;
  12. ElfW(Addr) loadaddr = -1;
  13. ElfW(Dyn) *dpnt;
  14. struct stat st;
  15. char *needed;
  16. char *soname = NULL;
  17. int multi_libcs = 0;
  18. if (expected_type == LIB_DLL) {
  19. warn("%s does not match type specified for directory!", name);
  20. expected_type = LIB_ANY;
  21. }
  22. *type = LIB_ELF;
  23. if (fstat(fileno(infile), &st))
  24. return NULL;
  25. header =
  26. mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
  27. fileno(infile), 0);
  28. if (header == (caddr_t) - 1)
  29. return NULL;
  30. epnt = (ElfW(Ehdr) *) header;
  31. if ((char *)(epnt + 1) > (char *)(header + st.st_size))
  32. goto skip;
  33. if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE)
  34. byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
  35. else if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG)
  36. byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
  37. /* Be very lazy, and only byteswap the stuff we use */
  38. if (byteswap == 1) {
  39. epnt->e_phoff = bswap_32(epnt->e_phoff);
  40. epnt->e_phnum = bswap_16(epnt->e_phnum);
  41. }
  42. ppnt = (ElfW(Phdr) *) & header[epnt->e_phoff];
  43. if ((char *)ppnt < (char *)header ||
  44. (char *)(ppnt + epnt->e_phnum) > (char *)(header + st.st_size))
  45. goto skip;
  46. for (i = 0; i < epnt->e_phnum; i++) {
  47. /* Be very lazy, and only byteswap the stuff we use */
  48. if (byteswap == 1) {
  49. ppnt->p_type = bswap_32(ppnt->p_type);
  50. ppnt->p_vaddr = bswap_32(ppnt->p_vaddr);
  51. ppnt->p_offset = bswap_32(ppnt->p_offset);
  52. ppnt->p_filesz = bswap_32(ppnt->p_filesz);
  53. }
  54. if (loadaddr == (ElfW(Addr)) - 1 && ppnt->p_type == PT_LOAD)
  55. loadaddr = (ppnt->p_vaddr & ~(page_size - 1)) -
  56. (ppnt->p_offset & ~(page_size - 1));
  57. if (ppnt->p_type == 2) {
  58. dynamic_addr = ppnt->p_offset;
  59. dynamic_size = ppnt->p_filesz;
  60. };
  61. ppnt++;
  62. };
  63. dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
  64. dynamic_size = dynamic_size / sizeof(ElfW(Dyn));
  65. if ((char *)dpnt < (char *)header ||
  66. (char *)(dpnt + dynamic_size) > (char *)(header + st.st_size))
  67. goto skip;
  68. if (byteswap == 1) {
  69. dpnt->d_tag = bswap_32(dpnt->d_tag);
  70. dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val);
  71. }
  72. while (dpnt->d_tag != DT_NULL) {
  73. if (dpnt->d_tag == DT_STRTAB)
  74. strtab_val = dpnt->d_un.d_val;
  75. dpnt++;
  76. if (byteswap == 1) {
  77. dpnt->d_tag = bswap_32(dpnt->d_tag);
  78. dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val);
  79. }
  80. };
  81. if (!strtab_val)
  82. goto skip;
  83. dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
  84. while (dpnt->d_tag != DT_NULL) {
  85. if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) {
  86. needed_val = dpnt->d_un.d_val;
  87. if (needed_val + strtab_val >= loadaddr ||
  88. needed_val + strtab_val < st.st_size - loadaddr) {
  89. needed =
  90. (char *)(header - loadaddr + strtab_val +
  91. needed_val);
  92. if (dpnt->d_tag == DT_SONAME)
  93. soname = xstrdup(needed);
  94. for (j = 0; needed_tab[j].soname != NULL; j++) {
  95. if (strcmp(needed, needed_tab[j].soname)
  96. == 0) {
  97. if (*type != LIB_ELF
  98. && *type !=
  99. needed_tab[j].type)
  100. multi_libcs = 1;
  101. *type = needed_tab[j].type;
  102. }
  103. }
  104. }
  105. }
  106. dpnt++;
  107. };
  108. if (multi_libcs)
  109. warn("%s appears to be for multiple libc's", name);
  110. /* If we could not deduce the libc type, and we know what to expect, set the type */
  111. if (*type == LIB_ELF && expected_type != LIB_ANY)
  112. *type = expected_type;
  113. if (expected_type != LIB_ANY && expected_type != LIB_ELF &&
  114. expected_type != *type) {
  115. warn("%s does not match type specified for directory!", name);
  116. }
  117. skip:
  118. munmap(header, st.st_size);
  119. return soname;
  120. }