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
get_static_image_symbol(image_id image,const char * name,int32 symbolType,void ** _address)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
ElfImage()98 ElfImage::ElfImage()
99 : fImage(-1),
100 fFile(),
101 fTextAddress(NULL),
102 fDataAddress(NULL),
103 fGotAddress(NULL)
104 {
105 }
106
107 // destructor
~ElfImage()108 ElfImage::~ElfImage()
109 {
110 Unset();
111 }
112
113 // SetTo
114 status_t
SetTo(image_id image)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
Unset()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
Unload()137 ElfImage::Unload()
138 {
139 fFile.Unload();
140 }
141
142 // FindSymbol
143 status_t
FindSymbol(const char * symbolName,void ** address)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
GetSymbolRelocations(const char * symbolName,BList * relocations)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
_SetTo(image_id image)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