2 * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
17 #include <runtime_loader.h>
21 using namespace BPrivate::Debug
;
24 // #pragma mark - Image
38 Image::GetSymbol(const char* name
, int32 symbolType
, void** _symbolLocation
,
39 size_t* _symbolSize
, int32
* _symbolType
) const
41 // TODO: At least for ImageFile we could do hash lookups!
43 const char* foundName
;
48 while (NextSymbol(iterator
, &foundName
, &foundNameLen
, &foundAddress
,
49 &foundSize
, &foundType
) == B_OK
) {
50 if ((symbolType
== B_SYMBOL_TYPE_ANY
|| symbolType
== foundType
)
51 && strcmp(name
, foundName
) == 0) {
52 if (_symbolLocation
!= NULL
)
53 *_symbolLocation
= (void*)foundAddress
;
54 if (_symbolSize
!= NULL
)
55 *_symbolSize
= foundSize
;
56 if (_symbolType
!= NULL
)
57 *_symbolType
= foundType
;
62 return B_ENTRY_NOT_FOUND
;
66 // #pragma mark - SymbolTableBasedImage
69 SymbolTableBasedImage::SymbolTableBasedImage()
80 SymbolTableBasedImage::~SymbolTableBasedImage()
86 SymbolTableBasedImage::LookupSymbol(addr_t address
, addr_t
* _baseAddress
,
87 const char** _symbolName
, size_t *_symbolNameLen
, bool *_exactMatch
) const
89 const elf_sym
* symbolFound
= NULL
;
90 const char* symbolName
= NULL
;
91 bool exactMatch
= false;
92 addr_t deltaFound
= ~(addr_t
)0;
94 for (int32 i
= 0; i
< fSymbolCount
; i
++) {
95 const elf_sym
* symbol
= &fSymbolTable
[i
];
97 if (symbol
->st_value
== 0
98 || symbol
->st_size
>= (size_t)fInfo
.text_size
+ fInfo
.data_size
) {
102 addr_t symbolAddress
= symbol
->st_value
+ fLoadDelta
;
103 if (symbolAddress
> address
)
106 addr_t symbolDelta
= address
- symbolAddress
;
107 if (symbolDelta
>= 0 && symbolDelta
< symbol
->st_size
)
110 if (exactMatch
|| symbolDelta
< deltaFound
) {
111 deltaFound
= symbolDelta
;
112 symbolFound
= symbol
;
113 symbolName
= fStringTable
+ symbol
->st_name
;
120 if (symbolFound
!= NULL
) {
121 if (_baseAddress
!= NULL
)
122 *_baseAddress
= symbolFound
->st_value
+ fLoadDelta
;
123 if (_symbolName
!= NULL
)
124 *_symbolName
= symbolName
;
125 if (_exactMatch
!= NULL
)
126 *_exactMatch
= exactMatch
;
127 if (_symbolNameLen
!= NULL
)
128 *_symbolNameLen
= _SymbolNameLen(symbolName
);
136 SymbolTableBasedImage::NextSymbol(int32
& iterator
, const char** _symbolName
,
137 size_t* _symbolNameLen
, addr_t
* _symbolAddress
, size_t* _symbolSize
,
138 int32
* _symbolType
) const
141 if (++iterator
>= fSymbolCount
)
142 return B_ENTRY_NOT_FOUND
;
144 const elf_sym
* symbol
= &fSymbolTable
[iterator
];
146 if ((symbol
->Type() != STT_FUNC
&& symbol
->Type() != STT_OBJECT
)
147 || symbol
->st_value
== 0) {
151 *_symbolName
= fStringTable
+ symbol
->st_name
;
152 *_symbolNameLen
= _SymbolNameLen(*_symbolName
);
153 *_symbolAddress
= symbol
->st_value
+ fLoadDelta
;
154 *_symbolSize
= symbol
->st_size
;
155 *_symbolType
= symbol
->Type() == STT_FUNC
? B_SYMBOL_TYPE_TEXT
156 : B_SYMBOL_TYPE_DATA
;
164 SymbolTableBasedImage::_SymbolNameLen(const char* symbolName
) const
166 if (symbolName
== NULL
|| (addr_t
)symbolName
< (addr_t
)fStringTable
167 || (addr_t
)symbolName
>= (addr_t
)fStringTable
+ fStringTableSize
) {
171 return strnlen(symbolName
,
172 (addr_t
)fStringTable
+ fStringTableSize
- (addr_t
)symbolName
);
176 // #pragma mark - ImageFile
179 ImageFile::ImageFile()
183 fMappedFile((uint8
*)MAP_FAILED
)
188 ImageFile::~ImageFile()
190 if (fMappedFile
!= MAP_FAILED
)
191 munmap(fMappedFile
, fFileSize
);
199 ImageFile::Init(const image_info
& info
)
201 // just copy the image info
209 status_t error
= _LoadFile(info
.name
, &textAddress
, &textSize
, &dataAddress
,
214 // compute the load delta
215 fLoadDelta
= (addr_t
)fInfo
.text
- textAddress
;
222 ImageFile::Init(const char* path
)
229 status_t error
= _LoadFile(path
, &textAddress
, &textSize
, &dataAddress
,
234 // init the image info
236 fInfo
.type
= B_LIBRARY_IMAGE
;
238 fInfo
.init_order
= 0;
239 fInfo
.init_routine
= 0;
240 fInfo
.term_routine
= 0;
243 strlcpy(fInfo
.name
, path
, sizeof(fInfo
.name
));
244 fInfo
.text
= (void*)textAddress
;
245 fInfo
.data
= (void*)dataAddress
;
246 fInfo
.text_size
= textSize
;
247 fInfo
.data_size
= dataSize
;
249 // the image isn't loaded, so no delta
257 ImageFile::_LoadFile(const char* path
, addr_t
* _textAddress
, size_t* _textSize
,
258 addr_t
* _dataAddress
, size_t* _dataSize
)
260 // open and stat() the file
261 fFD
= open(path
, O_RDONLY
);
266 if (fstat(fFD
, &st
) < 0)
269 fFileSize
= st
.st_size
;
270 if (fFileSize
< (off_t
)sizeof(elf_ehdr
))
271 return B_NOT_AN_EXECUTABLE
;
274 fMappedFile
= (uint8
*)mmap(NULL
, fFileSize
, PROT_READ
, MAP_PRIVATE
, fFD
, 0);
275 if (fMappedFile
== MAP_FAILED
)
278 // examine the elf header
279 elf_ehdr
* elfHeader
= (elf_ehdr
*)fMappedFile
;
280 if (memcmp(elfHeader
->e_ident
, ELF_MAGIC
, 4) != 0)
281 return B_NOT_AN_EXECUTABLE
;
283 if (elfHeader
->e_ident
[4] != ELF_CLASS
)
284 return B_NOT_AN_EXECUTABLE
;
286 // verify the location of the program headers
287 int32 programHeaderCount
= elfHeader
->e_phnum
;
288 if (elfHeader
->e_phoff
< sizeof(elf_ehdr
)
289 || elfHeader
->e_phentsize
< sizeof(elf_phdr
)
290 || (off_t
)(elfHeader
->e_phoff
+ programHeaderCount
291 * elfHeader
->e_phentsize
)
293 return B_NOT_AN_EXECUTABLE
;
296 elf_phdr
* programHeaders
297 = (elf_phdr
*)(fMappedFile
+ elfHeader
->e_phoff
);
299 // verify the location of the section headers
300 int32 sectionCount
= elfHeader
->e_shnum
;
301 if (elfHeader
->e_shoff
< sizeof(elf_ehdr
)
302 || elfHeader
->e_shentsize
< sizeof(elf_shdr
)
303 || (off_t
)(elfHeader
->e_shoff
+ sectionCount
* elfHeader
->e_shentsize
)
305 return B_NOT_AN_EXECUTABLE
;
308 // find the text and data segment -- we need load address and size
313 for (int32 i
= 0; i
< programHeaderCount
; i
++) {
314 elf_phdr
* header
= (elf_phdr
*)
315 ((uint8
*)programHeaders
+ i
* elfHeader
->e_phentsize
);
316 if (header
->p_type
== PT_LOAD
) {
317 if ((header
->p_flags
& PF_WRITE
) == 0) {
318 *_textAddress
= header
->p_vaddr
;
319 *_textSize
= header
->p_memsz
;
321 *_dataAddress
= header
->p_vaddr
;
322 *_dataSize
= header
->p_memsz
;
328 status_t error
= _FindTableInSection(elfHeader
, SHT_SYMTAB
);
330 error
= _FindTableInSection(elfHeader
, SHT_DYNSYM
);
337 ImageFile::_FindTableInSection(elf_ehdr
* elfHeader
, uint16 sectionType
)
339 elf_shdr
* sectionHeaders
340 = (elf_shdr
*)(fMappedFile
+ elfHeader
->e_shoff
);
342 // find the symbol table
343 for (int32 i
= 0; i
< elfHeader
->e_shnum
; i
++) {
344 elf_shdr
* sectionHeader
= (elf_shdr
*)
345 ((uint8
*)sectionHeaders
+ i
* elfHeader
->e_shentsize
);
347 if (sectionHeader
->sh_type
== sectionType
) {
348 elf_shdr
& stringHeader
= *(elf_shdr
*)
349 ((uint8
*)sectionHeaders
350 + sectionHeader
->sh_link
* elfHeader
->e_shentsize
);
352 if (stringHeader
.sh_type
!= SHT_STRTAB
)
355 if ((off_t
)(sectionHeader
->sh_offset
+ sectionHeader
->sh_size
)
357 || (off_t
)(stringHeader
.sh_offset
+ stringHeader
.sh_size
)
362 fSymbolTable
= (elf_sym
*)(fMappedFile
+ sectionHeader
->sh_offset
);
363 fStringTable
= (char*)(fMappedFile
+ stringHeader
.sh_offset
);
364 fSymbolCount
= sectionHeader
->sh_size
/ sizeof(elf_sym
);
365 fStringTableSize
= stringHeader
.sh_size
;
375 // #pragma mark - KernelImage
378 KernelImage::KernelImage()
383 KernelImage::~KernelImage()
385 delete[] fSymbolTable
;
386 delete[] fStringTable
;
391 KernelImage::Init(const image_info
& info
)
395 // get the table sizes
397 fStringTableSize
= 0;
398 status_t error
= _kern_read_kernel_image_symbols(fInfo
.id
,
399 NULL
, &fSymbolCount
, NULL
, &fStringTableSize
, NULL
);
403 // allocate the tables
404 fSymbolTable
= new(std::nothrow
) elf_sym
[fSymbolCount
];
405 fStringTable
= new(std::nothrow
) char[fStringTableSize
];
406 if (fSymbolTable
== NULL
|| fStringTable
== NULL
)
410 return _kern_read_kernel_image_symbols(fInfo
.id
,
411 fSymbolTable
, &fSymbolCount
, fStringTable
, &fStringTableSize
,
416 CommPageImage::CommPageImage()
421 CommPageImage::~CommPageImage()
423 delete[] fSymbolTable
;
424 delete[] fStringTable
;
429 CommPageImage::Init(const image_info
& info
)
431 // find kernel image for commpage
432 image_id commPageID
= -1;
433 image_info commPageInfo
;
436 while (_kern_get_next_image_info(B_SYSTEM_TEAM
, &cookie
, &commPageInfo
,
437 sizeof(image_info
)) == B_OK
) {
438 if (!strcmp("commpage", commPageInfo
.name
)) {
439 commPageID
= commPageInfo
.id
;
444 return B_ENTRY_NOT_FOUND
;
446 fInfo
= commPageInfo
;
447 fInfo
.text
= info
.text
;
449 // get the table sizes
451 fStringTableSize
= 0;
452 status_t error
= _kern_read_kernel_image_symbols(commPageID
, NULL
,
453 &fSymbolCount
, NULL
, &fStringTableSize
, NULL
);
457 // allocate the tables
458 fSymbolTable
= new(std::nothrow
) elf_sym
[fSymbolCount
];
459 fStringTable
= new(std::nothrow
) char[fStringTableSize
];
460 if (fSymbolTable
== NULL
|| fStringTable
== NULL
)
464 error
= _kern_read_kernel_image_symbols(commPageID
,
465 fSymbolTable
, &fSymbolCount
, fStringTable
, &fStringTableSize
, NULL
);
467 delete[] fSymbolTable
;
468 delete[] fStringTable
;
472 fLoadDelta
= (addr_t
)info
.text
;