]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.base/sym-file-loader.c
1 /* Copyright 2013-2014 Free Software Foundation, Inc.
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 3 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "sym-file-loader.h"
28 elf_st_type (uint8_t st_info
)
30 return ELF64_ST_TYPE (st_info
);
33 #elif defined TARGET_ILP32
36 elf_st_type (uint8_t st_info
)
38 return ELF32_ST_TYPE (st_info
);
43 /* Load a program segment. */
45 static struct segment
*
46 load (uint8_t *addr
, Elf_External_Phdr
*phdr
, struct segment
*tail_seg
)
48 struct segment
*seg
= NULL
;
49 uint8_t *mapped_addr
= NULL
;
53 /* For the sake of simplicity all operations are permitted. */
54 unsigned perm
= PROT_READ
| PROT_WRITE
| PROT_EXEC
;
56 mapped_addr
= (uint8_t *) mmap ((void *) GETADDR (phdr
, p_vaddr
),
57 GET (phdr
, p_memsz
), perm
,
58 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
60 from
= (void *) (addr
+ GET (phdr
, p_offset
));
61 to
= (void *) mapped_addr
;
63 memcpy (to
, from
, GET (phdr
, p_filesz
));
65 seg
= (struct segment
*) malloc (sizeof (struct segment
));
70 seg
->mapped_addr
= mapped_addr
;
80 /* Mini shared library loader. No reallocation
81 is performed for the sake of simplicity. */
84 load_shlib (const char *file
, Elf_External_Ehdr
**ehdr_out
,
85 struct segment
**seg_out
)
91 Elf_External_Ehdr
*ehdr
;
92 Elf_External_Phdr
*phdr
;
93 struct segment
*head_seg
= NULL
;
94 struct segment
*tail_seg
= NULL
;
96 /* Map the lib in memory for reading. */
97 fd
= open (file
, O_RDONLY
);
100 perror ("fopen failed.");
104 fsize
= lseek (fd
, 0, SEEK_END
);
108 perror ("lseek failed.");
112 addr
= (uint8_t *) mmap (NULL
, fsize
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
113 if (addr
== (uint8_t *) -1)
115 perror ("mmap failed.");
119 /* Check if the lib is an ELF file. */
120 ehdr
= (Elf_External_Ehdr
*) addr
;
121 if (ehdr
->e_ident
[EI_MAG0
] != ELFMAG0
122 || ehdr
->e_ident
[EI_MAG1
] != ELFMAG1
123 || ehdr
->e_ident
[EI_MAG2
] != ELFMAG2
124 || ehdr
->e_ident
[EI_MAG3
] != ELFMAG3
)
126 printf ("Not an ELF file: %x\n", ehdr
->e_ident
[EI_MAG0
]);
130 if (ehdr
->e_ident
[EI_CLASS
] == ELFCLASS32
)
132 if (sizeof (void *) != 4)
134 printf ("Architecture mismatch.");
138 else if (ehdr
->e_ident
[EI_CLASS
] == ELFCLASS64
)
140 if (sizeof (void *) != 8)
142 printf ("Architecture mismatch.");
147 /* Load the program segments. For the sake of simplicity
148 assume that no reallocation is needed. */
149 phdr
= (Elf_External_Phdr
*) (addr
+ GET (ehdr
, e_phoff
));
150 for (i
= 0; i
< GET (ehdr
, e_phnum
); i
++, phdr
++)
152 if (GET (phdr
, p_type
) == PT_LOAD
)
154 struct segment
*next_seg
= load (addr
, phdr
, tail_seg
);
167 /* Return the section-header table. */
170 find_shdrtab (Elf_External_Ehdr
*ehdr
)
172 return (Elf_External_Shdr
*) (((uint8_t *) ehdr
) + GET (ehdr
, e_shoff
));
175 /* Return the string table of the section headers. */
178 find_shstrtab (Elf_External_Ehdr
*ehdr
, uint64_t *size
)
180 const Elf_External_Shdr
*shdr
;
181 const Elf_External_Shdr
*shstr
;
183 if (GET (ehdr
, e_shnum
) <= GET (ehdr
, e_shstrndx
))
185 printf ("The index of the string table is corrupt.");
189 shdr
= find_shdrtab (ehdr
);
191 shstr
= &shdr
[GET (ehdr
, e_shstrndx
)];
192 *size
= GET (shstr
, sh_size
);
193 return ((const char *) ehdr
) + GET (shstr
, sh_offset
);
196 /* Return the string table named SECTION. */
199 find_strtab (Elf_External_Ehdr
*ehdr
,
200 const char *section
, uint64_t *strtab_size
)
202 uint64_t shstrtab_size
= 0;
203 const char *shstrtab
;
205 const Elf_External_Shdr
*shdr
= find_shdrtab (ehdr
);
207 /* Get the string table of the section headers. */
208 shstrtab
= find_shstrtab (ehdr
, &shstrtab_size
);
209 if (shstrtab
== NULL
)
212 for (i
= 0; i
< GET (ehdr
, e_shnum
); i
++)
214 uint64_t name
= GET (shdr
+ i
, sh_name
);
215 if (GET (shdr
+ i
, sh_type
) == SHT_STRTAB
&& name
<= shstrtab_size
216 && strcmp ((const char *) &shstrtab
[name
], section
) == 0)
218 *strtab_size
= GET (shdr
+ i
, sh_size
);
219 return ((const char *) ehdr
) + GET (shdr
+ i
, sh_offset
);
226 /* Return the section header named SECTION. */
229 find_shdr (Elf_External_Ehdr
*ehdr
, const char *section
)
231 uint64_t shstrtab_size
= 0;
232 const char *shstrtab
;
235 /* Get the string table of the section headers. */
236 shstrtab
= find_shstrtab (ehdr
, &shstrtab_size
);
237 if (shstrtab
== NULL
)
240 Elf_External_Shdr
*shdr
= find_shdrtab (ehdr
);
241 for (i
= 0; i
< GET (ehdr
, e_shnum
); i
++)
243 uint64_t name
= GET (shdr
+ i
, sh_name
);
244 if (name
<= shstrtab_size
)
246 if (strcmp ((const char *) &shstrtab
[name
], section
) == 0)
254 /* Return the symbol table. */
257 find_symtab (Elf_External_Ehdr
*ehdr
, uint64_t *symtab_size
)
260 const Elf_External_Shdr
*shdr
= find_shdrtab (ehdr
);
262 for (i
= 0; i
< GET (ehdr
, e_shnum
); i
++)
264 if (GET (shdr
+ i
, sh_type
) == SHT_SYMTAB
)
266 *symtab_size
= GET (shdr
+ i
, sh_size
) / sizeof (Elf_External_Sym
);
267 return (Elf_External_Sym
*) (((const char *) ehdr
) +
268 GET (shdr
+ i
, sh_offset
));
274 /* Translate a file offset to an address in a loaded segment. */
277 translate_offset (uint64_t file_offset
, struct segment
*seg
, void **addr
)
281 uint64_t p_from
, p_to
;
283 Elf_External_Phdr
*phdr
= seg
->phdr
;
291 p_from
= GET (phdr
, p_offset
);
292 p_to
= p_from
+ GET (phdr
, p_filesz
);
294 if (p_from
<= file_offset
&& file_offset
< p_to
)
296 *addr
= (void *) (seg
->mapped_addr
+ (file_offset
- p_from
));
305 /* Lookup the address of FUNC. */
308 lookup_function (const char *func
,
309 Elf_External_Ehdr
*ehdr
, struct segment
*seg
, void **addr
)
312 uint64_t strtab_size
= 0;
313 Elf_External_Sym
*symtab
;
314 uint64_t symtab_size
= 0;
317 /* Get the string table for the symbols. */
318 strtab
= find_strtab (ehdr
, ".strtab", &strtab_size
);
321 printf (".strtab not found.");
325 /* Get the symbol table. */
326 symtab
= find_symtab (ehdr
, &symtab_size
);
329 printf ("symbol table not found.");
333 for (i
= 0; i
< symtab_size
; i
++)
335 Elf_External_Sym
*sym
= &symtab
[i
];
337 if (elf_st_type (GET (sym
, st_info
)) != STT_FUNC
)
340 if (GET (sym
, st_name
) < strtab_size
)
342 const char *name
= &strtab
[GET (sym
, st_name
)];
343 if (strcmp (name
, func
) == 0)
346 uint64_t offset
= GET (sym
, st_value
);
347 return translate_offset (offset
, seg
, addr
);