1 /*
2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "SharedImage.h"
8
9 #include <stdio.h>
10
11 #include <algorithm>
12 #include <new>
13
14 #include <debug_support.h>
15 #include <ObjectList.h>
16
17 #include "Options.h"
18
19
SharedImage()20 SharedImage::SharedImage()
21 :
22 fSymbols(NULL),
23 fSymbolCount(0)
24 {
25 }
26
27
~SharedImage()28 SharedImage::~SharedImage()
29 {
30 if (fSymbols != NULL) {
31 for (int32 i = 0; i < fSymbolCount; i++)
32 delete fSymbols[i];
33 delete[] fSymbols;
34 }
35 }
36
37
38 status_t
Init(team_id owner,image_id imageID)39 SharedImage::Init(team_id owner, image_id imageID)
40 {
41 // we need a temporary symbol lookup context
42 debug_symbol_lookup_context* lookupContext;
43 status_t error = debug_create_symbol_lookup_context(owner, imageID,
44 &lookupContext);
45 if (error != B_OK) {
46 fprintf(stderr, "%s: Failed to create symbol lookup context "
47 "for team %" B_PRId32 ": %s\n",
48 kCommandName, owner, strerror(error));
49 return error;
50 }
51
52 // TODO: Creating a symbol lookup just for loading the symbols of a single
53 // image is unnecessarily expensive.
54
55 // create a symbol iterator
56 debug_symbol_iterator* iterator;
57 error = debug_create_image_symbol_iterator(lookupContext, imageID,
58 &iterator);
59 if (error != B_OK) {
60 fprintf(stderr,
61 "Failed to init symbol iterator for image %" B_PRId32 ": %s\n",
62 imageID, strerror(error));
63 debug_delete_symbol_lookup_context(lookupContext);
64 return error;
65 }
66
67 // init
68 error = _Init(iterator);
69
70 // cleanup
71 debug_delete_symbol_iterator(iterator);
72 debug_delete_symbol_lookup_context(lookupContext);
73
74 return error;
75 }
76
77
78 status_t
Init(const char * path)79 SharedImage::Init(const char* path)
80 {
81 // create a symbol iterator
82 debug_symbol_iterator* iterator;
83 status_t error = debug_create_file_symbol_iterator(path, &iterator);
84 if (error != B_OK) {
85 fprintf(stderr, "Failed to init symbol iterator for \"%s\": %s\n",
86 path, strerror(error));
87 return error;
88 }
89
90 error = _Init(iterator);
91
92 debug_delete_symbol_iterator(iterator);
93
94 return error;
95 }
96
97
98 int32
FindSymbol(addr_t address) const99 SharedImage::FindSymbol(addr_t address) const
100 {
101 // binary search the function
102 int32 lower = 0;
103 int32 upper = fSymbolCount;
104
105 while (lower < upper) {
106 int32 mid = (lower + upper) / 2;
107 if (address >= fSymbols[mid]->base + fSymbols[mid]->size)
108 lower = mid + 1;
109 else
110 upper = mid;
111 }
112
113 if (lower == fSymbolCount)
114 return -1;
115
116 const Symbol* symbol = fSymbols[lower];
117 if (address >= symbol->base && address < symbol->base + symbol->size)
118 return lower;
119 return -1;
120 }
121
122
123 status_t
_Init(debug_symbol_iterator * iterator)124 SharedImage::_Init(debug_symbol_iterator* iterator)
125 {
126 // get an image info
127 status_t error = debug_get_symbol_iterator_image_info(iterator, &fInfo);
128 if (error != B_OK)
129 return error;
130
131 // iterate through the symbols
132 BObjectList<Symbol> symbols(512, true);
133 char symbolName[1024];
134 int32 symbolType;
135 void* symbolLocation;
136 size_t symbolSize;
137 while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName),
138 &symbolType, &symbolLocation, &symbolSize) == B_OK) {
139 // printf(" %s %p (%6lu) %s\n",
140 // symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data",
141 // symbolLocation, symbolSize, symbolName);
142 if (symbolSize > 0 && symbolType == B_SYMBOL_TYPE_TEXT) {
143 Symbol* symbol = new(std::nothrow) Symbol(this,
144 (addr_t)symbolLocation, symbolSize, symbolName);
145 if (symbol == NULL || !symbols.AddItem(symbol)) {
146 delete symbol;
147 fprintf(stderr, "%s: Out of memory\n", kCommandName);
148 return B_NO_MEMORY;
149 }
150 }
151 }
152
153 // sort the symbols
154 fSymbolCount = symbols.CountItems();
155 fSymbols = new(std::nothrow) Symbol*[fSymbolCount];
156 if (fSymbols == NULL)
157 return B_NO_MEMORY;
158
159 for (int32 i = fSymbolCount - 1; i >= 0 ; i--)
160 fSymbols[i] = symbols.RemoveItemAt(i);
161
162 std::sort(fSymbols, fSymbols + fSymbolCount, SymbolComparator());
163
164 return B_OK;
165 }
166