1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2003, Ingo Weinhold 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: ElfImage.cpp 23 // Author: Ingo Weinhold (bonefish@users.sf.net) 24 // Description: Implementation of ElfImage, a class encapsulating 25 // a loaded ELF image, providing support for accessing the 26 // image's symbols and their relocation entries. 27 //------------------------------------------------------------------------------ 28 29 #include <new> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #include <List.h> 35 36 #include <debug/debug_support.h> 37 38 #include "ElfImage.h" 39 40 41 static status_t 42 get_static_image_symbol(image_id image, const char* name, int32 symbolType, 43 void** _address) 44 { 45 // try standard lookup first 46 status_t error = get_image_symbol(image, name, symbolType, _address); 47 if (error == B_OK) 48 return B_OK; 49 50 // get an image info 51 image_info imageInfo; 52 error = get_image_info(image, &imageInfo); 53 if (error != B_OK) 54 return error; 55 56 // get a symbol iterator 57 debug_symbol_iterator* iterator; 58 error = debug_create_file_symbol_iterator(imageInfo.name, &iterator); 59 if (error != B_OK) 60 return error; 61 62 // get the unrelocated image info 63 image_info unrelocatedImageInfo; 64 error = debug_get_symbol_iterator_image_info(iterator, 65 &unrelocatedImageInfo); 66 if (error != B_OK) { 67 debug_delete_symbol_iterator(iterator); 68 return error; 69 } 70 71 // iterate through the symbols 72 int32 nameLength = strlen(name); 73 while (true) { 74 char foundName[nameLength + 1]; 75 int32 foundType; 76 void* foundAddress; 77 size_t foundSize; 78 if (debug_next_image_symbol(iterator, foundName, nameLength + 1, 79 &foundType, &foundAddress, &foundSize) != B_OK) { 80 debug_delete_symbol_iterator(iterator); 81 return B_ENTRY_NOT_FOUND; 82 } 83 84 if (strcmp(foundName, name) == 0 85 && (symbolType == B_SYMBOL_TYPE_ANY || foundType == symbolType)) { 86 *_address = (void*)((addr_t)foundAddress + (addr_t)imageInfo.text 87 - (addr_t)unrelocatedImageInfo.text); 88 debug_delete_symbol_iterator(iterator); 89 return B_OK; 90 } 91 } 92 } 93 94 95 // ElfImage 96 97 // constructor 98 ElfImage::ElfImage() 99 : fImage(-1), 100 fFile(), 101 fTextAddress(NULL), 102 fDataAddress(NULL), 103 fGotAddress(NULL) 104 { 105 } 106 107 // destructor 108 ElfImage::~ElfImage() 109 { 110 Unset(); 111 } 112 113 // SetTo 114 status_t 115 ElfImage::SetTo(image_id image) 116 { 117 Unset(); 118 status_t error = _SetTo(image); 119 if (error) 120 Unset(); 121 return error; 122 } 123 124 // Unset 125 void 126 ElfImage::Unset() 127 { 128 fFile.Unset(); 129 fImage = -1; 130 fTextAddress = NULL; 131 fDataAddress = NULL; 132 fGotAddress = NULL; 133 } 134 135 // Unload 136 void 137 ElfImage::Unload() 138 { 139 fFile.Unload(); 140 } 141 142 // FindSymbol 143 status_t 144 ElfImage::FindSymbol(const char* symbolName, void** address) 145 { 146 return get_image_symbol(fImage, symbolName, B_SYMBOL_TYPE_ANY, address); 147 } 148 149 // GetSymbolRelocations 150 status_t 151 ElfImage::GetSymbolRelocations(const char* symbolName, BList* relocations) 152 { 153 status_t error = B_OK; 154 ElfRelocation relocation; 155 for (ElfRelocationIterator it(&fFile); it.GetNext(&relocation); ) { 156 uint32 type = relocation.GetType(); 157 // get the symbol 158 ElfSymbol symbol; 159 if ((type == R_GLOB_DAT || type == R_JUMP_SLOT) 160 && relocation.GetSymbol(&symbol) == B_OK 161 && symbol.GetName()) { 162 // only undefined symbols with global binding 163 if ((symbol.GetBinding() == STB_GLOBAL 164 || symbol.GetBinding() == STB_WEAK) 165 && (symbol.GetTargetSectionIndex() == SHN_UNDEF 166 || symbol.GetTargetSectionIndex() 167 >= (uint32)fFile.CountSections()) 168 && !strcmp(symbol.GetName(), symbolName)) { 169 // get the address of the GOT entry for the symbol 170 void** gotEntry 171 = (void**)(fTextAddress + relocation.GetOffset()); 172 if (!relocations->AddItem(gotEntry)) { 173 error = B_NO_MEMORY; 174 break; 175 } 176 } 177 } 178 } 179 return error; 180 } 181 182 183 // _SetTo 184 status_t 185 ElfImage::_SetTo(image_id image) 186 { 187 // get an image info 188 image_info imageInfo; 189 status_t error = get_image_info(image, &imageInfo); 190 if (error != B_OK) 191 return error; 192 fImage = imageInfo.id; 193 // get the address of global offset table 194 error = get_static_image_symbol(image, "_GLOBAL_OFFSET_TABLE_", 195 B_SYMBOL_TYPE_ANY, (void**)&fGotAddress); 196 if (error != B_OK) 197 return error; 198 fTextAddress = (uint8*)imageInfo.text; 199 fDataAddress = (uint8*)imageInfo.data; 200 // init the file 201 error = fFile.SetTo(imageInfo.name); 202 if (error != B_OK) 203 return error; 204 return B_OK; 205 } 206 207