xref: /haiku/src/tools/elfsymbolpatcher/ElfImage.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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 "ElfImage.h"
37 
38 // ElfImage
39 
40 // constructor
41 ElfImage::ElfImage()
42 	: fImage(-1),
43 	  fFile(),
44 	  fTextAddress(NULL),
45 	  fDataAddress(NULL),
46 	  fGotAddress(NULL)
47 {
48 }
49 
50 // destructor
51 ElfImage::~ElfImage()
52 {
53 	Unset();
54 }
55 
56 // SetTo
57 status_t
58 ElfImage::SetTo(image_id image)
59 {
60 	Unset();
61 	status_t error = _SetTo(image);
62 	if (error)
63 		Unset();
64 	return error;
65 }
66 
67 // Unset
68 void
69 ElfImage::Unset()
70 {
71 	fFile.Unset();
72 	fImage = -1;
73 	fTextAddress = NULL;
74 	fDataAddress = NULL;
75 	fGotAddress = NULL;
76 }
77 
78 // Unload
79 void
80 ElfImage::Unload()
81 {
82 	fFile.Unload();
83 }
84 
85 // FindSymbol
86 status_t
87 ElfImage::FindSymbol(const char* symbolName, void** address)
88 {
89 	return get_image_symbol(fImage, symbolName, B_SYMBOL_TYPE_ANY, address);
90 }
91 
92 // GetSymbolRelocations
93 status_t
94 ElfImage::GetSymbolRelocations(const char* symbolName, BList* relocations)
95 {
96 	status_t error = B_OK;
97 	ElfRelocation relocation;
98 	for (ElfRelocationIterator it(&fFile); it.GetNext(&relocation); ) {
99 		uint32 type = relocation.GetType();
100 		// get the symbol
101 		ElfSymbol symbol;
102 		if ((type == R_386_GLOB_DAT || type == R_386_JMP_SLOT)
103 			&& relocation.GetSymbol(&symbol) == B_OK
104 			&& symbol.GetName()) {
105 			// only undefined symbols with global binding
106 			if ((symbol.GetBinding() == STB_GLOBAL
107 				 || symbol.GetBinding() == STB_WEAK)
108 				&& (symbol.GetTargetSectionIndex() == SHN_UNDEF
109 					|| symbol.GetTargetSectionIndex()
110 					   >= (uint32)fFile.CountSections())
111 				&& !strcmp(symbol.GetName(), symbolName)) {
112 				// get the address of the GOT entry for the symbol
113 				void** gotEntry
114 					= (void**)(fTextAddress + relocation.GetOffset());
115 				if (!relocations->AddItem(gotEntry)) {
116 					error = B_NO_MEMORY;
117 					break;
118 				}
119 			}
120 		}
121 	}
122 	return error;
123 }
124 
125 // _SetTo
126 status_t
127 ElfImage::_SetTo(image_id image)
128 {
129 	// get an image info
130 	image_info imageInfo;
131 	status_t error = get_image_info(image, &imageInfo);
132 	if (error != B_OK)
133 		return error;
134 	fImage = imageInfo.id;
135 	// get the address of global offset table
136 	error = get_image_symbol(image, "_GLOBAL_OFFSET_TABLE_",
137 							 B_SYMBOL_TYPE_ANY, (void**)&fGotAddress);
138 	if (error != B_OK)
139 		return error;
140 	fTextAddress = (uint8*)imageInfo.text;
141 	fDataAddress = (uint8*)imageInfo.data;
142 	// init the file
143 	error = fFile.SetTo(imageInfo.name);
144 	if (error != B_OK)
145 		return error;
146 	return B_OK;
147 }
148 
149