xref: /haiku/src/bin/debug/profile/SharedImage.cpp (revision 4de612c9b5555ad82966f60c06f84607c6cc31fe)
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