readsoname2.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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, MAP_SHARED, 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. ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff];
  33. if ((char *)ppnt < (char *)header ||
  34. (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size))
  35. goto skip;
  36. for(i = 0; i < epnt->e_phnum; i++)
  37. {
  38. if (loadaddr == -1 && ppnt->p_type == PT_LOAD)
  39. loadaddr = (ppnt->p_vaddr & ~(page_size-1)) -
  40. (ppnt->p_offset & ~(page_size-1));
  41. if(ppnt->p_type == 2)
  42. {
  43. dynamic_addr = ppnt->p_offset;
  44. dynamic_size = ppnt->p_filesz;
  45. };
  46. ppnt++;
  47. };
  48. dpnt = (ElfW(Dyn) *) &header[dynamic_addr];
  49. dynamic_size = dynamic_size / sizeof(ElfW(Dyn));
  50. if ((char *)dpnt < (char *)header ||
  51. (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size))
  52. goto skip;
  53. while (dpnt->d_tag != DT_NULL)
  54. {
  55. if (dpnt->d_tag == DT_STRTAB)
  56. strtab_val = dpnt->d_un.d_val;
  57. dpnt++;
  58. };
  59. if (!strtab_val)
  60. goto skip;
  61. dpnt = (ElfW(Dyn) *) &header[dynamic_addr];
  62. while (dpnt->d_tag != DT_NULL)
  63. {
  64. if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED)
  65. {
  66. needed_val = dpnt->d_un.d_val;
  67. if (needed_val + strtab_val - loadaddr >= 0 ||
  68. needed_val + strtab_val - loadaddr < st.st_size)
  69. {
  70. needed = (char *) (header - loadaddr + strtab_val + needed_val);
  71. if (dpnt->d_tag == DT_SONAME)
  72. soname = xstrdup(needed);
  73. for (j = 0; needed_tab[j].soname != NULL; j++)
  74. {
  75. if (strcmp(needed, needed_tab[j].soname) == 0)
  76. {
  77. if (*type != LIB_ELF && *type != needed_tab[j].type)
  78. multi_libcs = 1;
  79. *type = needed_tab[j].type;
  80. }
  81. }
  82. }
  83. }
  84. dpnt++;
  85. };
  86. if (multi_libcs)
  87. warn("%s appears to be for multiple libc's", name);
  88. /* If we could not deduce the libc type, and we know what to expect, set the type */
  89. if(*type == LIB_ELF && expected_type != LIB_ANY) *type = expected_type;
  90. if(expected_type != LIB_ANY && expected_type != LIB_ELF &&
  91. expected_type != *type)
  92. {
  93. warn("%s does not match type specified for directory!", name);
  94. }
  95. skip:
  96. munmap(header, st.st_size);
  97. return soname;
  98. }