]>
Commit | Line | Data |
---|---|---|
66f269d2 EA |
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 | ||
19 | if(expected_type == LIB_DLL) | |
20 | { | |
21 | warn("%s does not match type specified for directory!", name); | |
22 | expected_type = LIB_ANY; | |
23 | } | |
24 | ||
25 | *type = LIB_ELF; | |
26 | ||
27 | if (fstat(fileno(infile), &st)) | |
28 | return NULL; | |
29 | header = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(infile), 0); | |
30 | if (header == (caddr_t)-1) | |
31 | return NULL; | |
32 | ||
33 | epnt = (ElfW(Ehdr) *)header; | |
34 | if ((char *)(epnt+1) > (char *)(header + st.st_size)) | |
35 | goto skip; | |
36 | ||
37 | ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff]; | |
38 | if ((char *)ppnt < (char *)header || | |
39 | (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size)) | |
40 | goto skip; | |
41 | ||
42 | for(i = 0; i < epnt->e_phnum; i++) | |
43 | { | |
44 | if (loadaddr == -1 && ppnt->p_type == PT_LOAD) | |
45 | loadaddr = (ppnt->p_vaddr & ~(page_size-1)) - | |
46 | (ppnt->p_offset & ~(page_size-1)); | |
47 | if(ppnt->p_type == 2) | |
48 | { | |
49 | dynamic_addr = ppnt->p_offset; | |
50 | dynamic_size = ppnt->p_filesz; | |
51 | }; | |
52 | ppnt++; | |
53 | }; | |
54 | ||
55 | dpnt = (ElfW(Dyn) *) &header[dynamic_addr]; | |
56 | dynamic_size = dynamic_size / sizeof(ElfW(Dyn)); | |
57 | if ((char *)dpnt < (char *)header || | |
58 | (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size)) | |
59 | goto skip; | |
60 | ||
61 | while (dpnt->d_tag != DT_NULL) | |
62 | { | |
63 | if (dpnt->d_tag == DT_STRTAB) | |
64 | strtab_val = dpnt->d_un.d_val; | |
65 | dpnt++; | |
66 | }; | |
67 | ||
68 | if (!strtab_val) | |
69 | goto skip; | |
70 | ||
71 | dpnt = (ElfW(Dyn) *) &header[dynamic_addr]; | |
72 | while (dpnt->d_tag != DT_NULL) | |
73 | { | |
74 | if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) | |
75 | { | |
76 | needed_val = dpnt->d_un.d_val; | |
77 | if (needed_val + strtab_val - loadaddr >= 0 || | |
78 | needed_val + strtab_val - loadaddr < st.st_size) | |
79 | { | |
80 | needed = (char *) (header - loadaddr + strtab_val + needed_val); | |
81 | ||
82 | if (dpnt->d_tag == DT_SONAME) | |
83 | soname = xstrdup(needed); | |
84 | ||
85 | for (j = 0; needed_tab[j].soname != NULL; j++) | |
86 | { | |
87 | if (strcmp(needed, needed_tab[j].soname) == 0) | |
88 | { | |
89 | if (*type != LIB_ELF && *type != needed_tab[j].type) | |
90 | multi_libcs = 1; | |
91 | *type = needed_tab[j].type; | |
92 | } | |
93 | } | |
94 | } | |
95 | } | |
96 | dpnt++; | |
97 | }; | |
98 | ||
99 | if (multi_libcs) | |
100 | warn("%s appears to be for multiple libc's", name); | |
101 | ||
102 | /* If we could not deduce the libc type, and we know what to expect, set the type */ | |
103 | if(*type == LIB_ELF && expected_type != LIB_ANY) *type = expected_type; | |
104 | ||
105 | if(expected_type != LIB_ANY && expected_type != LIB_ELF && | |
106 | expected_type != *type) | |
107 | { | |
108 | warn("%s does not match type specified for directory!", name); | |
109 | } | |
110 | ||
111 | skip: | |
112 | munmap(header, st.st_size); | |
113 | ||
114 | return soname; | |
115 | } |