readsoname2.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. 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 __BYTE_ORDER == __LITTLE_ENDIAN
  34. byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
  35. #elif __BYTE_ORDER == __BIG_ENDIAN
  36. byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
  37. #else
  38. #error Unknown host byte order!
  39. #endif
  40. /* Be very lazy, and only byteswap the stuff we use */
  41. if (byteswap == 1) {
  42. epnt->e_phoff = bswap_32(epnt->e_phoff);
  43. epnt->e_phnum = bswap_16(epnt->e_phnum);
  44. }
  45. ppnt = (ElfW(Phdr) *) & header[epnt->e_phoff];
  46. if ((char *)ppnt < (char *)header ||
  47. (char *)(ppnt + epnt->e_phnum) > (char *)(header + st.st_size))
  48. goto skip;
  49. for (i = 0; i < epnt->e_phnum; i++) {
  50. /* Be very lazy, and only byteswap the stuff we use */
  51. if (byteswap == 1) {
  52. ppnt->p_type = bswap_32(ppnt->p_type);
  53. ppnt->p_vaddr = bswap_32(ppnt->p_vaddr);
  54. ppnt->p_offset = bswap_32(ppnt->p_offset);
  55. ppnt->p_filesz = bswap_32(ppnt->p_filesz);
  56. }
  57. if (loadaddr == (ElfW(Addr)) - 1 && ppnt->p_type == PT_LOAD)
  58. loadaddr = (ppnt->p_vaddr & ~(page_size - 1)) -
  59. (ppnt->p_offset & ~(page_size - 1));
  60. if (ppnt->p_type == 2) {
  61. dynamic_addr = ppnt->p_offset;
  62. dynamic_size = ppnt->p_filesz;
  63. };
  64. ppnt++;
  65. };
  66. dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
  67. dynamic_size = dynamic_size / sizeof(ElfW(Dyn));
  68. if ((char *)dpnt < (char *)header ||
  69. (char *)(dpnt + dynamic_size) > (char *)(header + st.st_size))
  70. goto skip;
  71. if (byteswap == 1) {
  72. dpnt->d_tag = bswap_32(dpnt->d_tag);
  73. dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val);
  74. }
  75. while (dpnt->d_tag != DT_NULL) {
  76. if (dpnt->d_tag == DT_STRTAB)
  77. strtab_val = dpnt->d_un.d_val;
  78. dpnt++;
  79. if (byteswap == 1) {
  80. dpnt->d_tag = bswap_32(dpnt->d_tag);
  81. dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val);
  82. }
  83. };
  84. if (!strtab_val)
  85. goto skip;
  86. dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
  87. while (dpnt->d_tag != DT_NULL) {
  88. if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) {
  89. needed_val = dpnt->d_un.d_val;
  90. if (needed_val + strtab_val >= loadaddr ||
  91. needed_val + strtab_val < st.st_size - loadaddr) {
  92. needed =
  93. (char *)(header - loadaddr + strtab_val +
  94. needed_val);
  95. if (dpnt->d_tag == DT_SONAME)
  96. soname = xstrdup(needed);
  97. for (j = 0; needed_tab[j].soname != NULL; j++) {
  98. if (strcmp(needed, needed_tab[j].soname)
  99. == 0) {
  100. if (*type != LIB_ELF
  101. && *type !=
  102. needed_tab[j].type)
  103. multi_libcs = 1;
  104. *type = needed_tab[j].type;
  105. }
  106. }
  107. }
  108. }
  109. dpnt++;
  110. };
  111. if (multi_libcs)
  112. warn("%s appears to be for multiple libc's", name);
  113. /* If we could not deduce the libc type, and we know what to expect, set the type */
  114. if (*type == LIB_ELF && expected_type != LIB_ANY)
  115. *type = expected_type;
  116. if (expected_type != LIB_ANY && expected_type != LIB_ELF &&
  117. expected_type != *type) {
  118. warn("%s does not match type specified for directory!", name);
  119. }
  120. skip:
  121. munmap(header, st.st_size);
  122. return soname;
  123. }