readsoname2.c 3.7 KB

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