xref: /haiku/src/tools/elfsymbolpatcher/ElfImage.cpp (revision 78058cf6d5c26d1a66584d0033c6fff5f3fd60d5)
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