sparc32: Add nop before __startcontext to stop unwinding
[uclibc-ng.git] / utils / readsoname2.c
blob5cda3318d7e0b16ffac37c67cfd895673ac2304c
1 static char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
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;
19 if (expected_type == LIB_DLL) {
20 warn("%s does not match type specified for directory!", name);
21 expected_type = LIB_ANY;
24 *type = LIB_ELF;
26 if (fstat(fileno(infile), &st))
27 return NULL;
28 header =
29 mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
30 fileno(infile), 0);
31 if (header == (caddr_t) - 1)
32 return NULL;
34 epnt = (ElfW(Ehdr) *) header;
35 if ((char *)(epnt + 1) > (char *)(header + st.st_size))
36 goto skip;
38 if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE)
39 byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
40 else if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG)
41 byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
43 /* Be very lazy, and only byteswap the stuff we use */
44 if (byteswap == 1) {
45 epnt->e_phoff = bswap_32(epnt->e_phoff);
46 epnt->e_phnum = bswap_16(epnt->e_phnum);
49 ppnt = (ElfW(Phdr) *) & header[epnt->e_phoff];
50 if ((char *)ppnt < (char *)header ||
51 (char *)(ppnt + epnt->e_phnum) > (char *)(header + st.st_size))
52 goto skip;
54 for (i = 0; i < epnt->e_phnum; i++) {
55 /* Be very lazy, and only byteswap the stuff we use */
56 if (byteswap == 1) {
57 ppnt->p_type = bswap_32(ppnt->p_type);
58 ppnt->p_vaddr = bswap_32(ppnt->p_vaddr);
59 ppnt->p_offset = bswap_32(ppnt->p_offset);
60 ppnt->p_filesz = bswap_32(ppnt->p_filesz);
63 if (loadaddr == (ElfW(Addr)) - 1 && ppnt->p_type == PT_LOAD)
64 loadaddr = (ppnt->p_vaddr & ~(page_size - 1)) -
65 (ppnt->p_offset & ~(page_size - 1));
66 if (ppnt->p_type == 2) {
67 dynamic_addr = ppnt->p_offset;
68 dynamic_size = ppnt->p_filesz;
70 ppnt++;
73 dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
74 dynamic_size = dynamic_size / sizeof(ElfW(Dyn));
75 if ((char *)dpnt < (char *)header ||
76 (char *)(dpnt + dynamic_size) > (char *)(header + st.st_size))
77 goto skip;
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);
84 while (dpnt->d_tag != DT_NULL) {
85 if (dpnt->d_tag == DT_STRTAB)
86 strtab_val = dpnt->d_un.d_val;
87 dpnt++;
88 if (byteswap == 1) {
89 dpnt->d_tag = bswap_32(dpnt->d_tag);
90 dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val);
94 if (!strtab_val)
95 goto skip;
97 dpnt = (ElfW(Dyn) *) & header[dynamic_addr];
98 while (dpnt->d_tag != DT_NULL) {
99 if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) {
100 needed_val = dpnt->d_un.d_val;
101 if (needed_val + strtab_val >= loadaddr ||
102 needed_val + strtab_val < st.st_size - loadaddr) {
103 needed =
104 (char *)(header - loadaddr + strtab_val +
105 needed_val);
107 if (dpnt->d_tag == DT_SONAME)
108 soname = xstrdup(needed);
110 for (j = 0; needed_tab[j].soname != NULL; j++) {
111 if (strcmp(needed, needed_tab[j].soname)
112 == 0) {
113 if (*type != LIB_ELF
114 && *type !=
115 needed_tab[j].type)
116 multi_libcs = 1;
117 *type = needed_tab[j].type;
122 dpnt++;
125 if (multi_libcs)
126 warn("%s appears to be for multiple libc's", name);
128 /* If we could not deduce the libc type, and we know what to expect, set the type */
129 if (*type == LIB_ELF && expected_type != LIB_ANY)
130 *type = expected_type;
132 if (expected_type != LIB_ANY && expected_type != LIB_ELF &&
133 expected_type != *type) {
134 warn("%s does not match type specified for directory!", name);
137 skip:
138 munmap(header, st.st_size);
140 return soname;