xref: /haiku/src/bin/debug/profile/SharedImage.cpp (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
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 
20 SharedImage::SharedImage()
21 	:
22 	fSymbols(NULL),
23 	fSymbolCount(0)
24 {
25 }
26 
27 
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
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 %ld: %s\n", kCommandName, owner, strerror(error));
48 		return error;
49 	}
50 
51 	// TODO: Creating a symbol lookup just for loading the symbols of a single
52 	// image is unnecessarily expensive.
53 
54 	// create a symbol iterator
55 	debug_symbol_iterator* iterator;
56 	error = debug_create_image_symbol_iterator(lookupContext, imageID,
57 		&iterator);
58 	if (error != B_OK) {
59 		fprintf(stderr, "Failed to init symbol iterator for image %ld: %s\n",
60 			imageID, strerror(error));
61 		debug_delete_symbol_lookup_context(lookupContext);
62 		return error;
63 	}
64 
65 	// init
66 	error = _Init(iterator);
67 
68 	// cleanup
69 	debug_delete_symbol_iterator(iterator);
70 	debug_delete_symbol_lookup_context(lookupContext);
71 
72 	return error;
73 }
74 
75 
76 status_t
77 SharedImage::Init(const char* path)
78 {
79 	// create a symbol iterator
80 	debug_symbol_iterator* iterator;
81 	status_t error = debug_create_file_symbol_iterator(path, &iterator);
82 	if (error != B_OK) {
83 		fprintf(stderr, "Failed to init symbol iterator for \"%s\": %s\n",
84 			path, strerror(error));
85 		return error;
86 	}
87 
88 	error = _Init(iterator);
89 
90 	debug_delete_symbol_iterator(iterator);
91 
92 	return error;
93 }
94 
95 
96 int32
97 SharedImage::FindSymbol(addr_t address) const
98 {
99 	// binary search the function
100 	int32 lower = 0;
101 	int32 upper = fSymbolCount;
102 
103 	while (lower < upper) {
104 		int32 mid = (lower + upper) / 2;
105 		if (address >= fSymbols[mid]->base + fSymbols[mid]->size)
106 			lower = mid + 1;
107 		else
108 			upper = mid;
109 	}
110 
111 	if (lower == fSymbolCount)
112 		return -1;
113 
114 	const Symbol* symbol = fSymbols[lower];
115 	if (address >= symbol->base && address < symbol->base + symbol->size)
116 		return lower;
117 	return -1;
118 }
119 
120 
121 status_t
122 SharedImage::_Init(debug_symbol_iterator* iterator)
123 {
124 	// get an image info
125 	status_t error = debug_get_symbol_iterator_image_info(iterator, &fInfo);
126 	if (error != B_OK)
127 		return error;
128 
129 	// iterate through the symbols
130 	BObjectList<Symbol>	symbols(512, true);
131 	char symbolName[1024];
132 	int32 symbolType;
133 	void* symbolLocation;
134 	size_t symbolSize;
135 	while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName),
136 			&symbolType, &symbolLocation, &symbolSize) == B_OK) {
137 //		printf("  %s %p (%6lu) %s\n",
138 //			symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data",
139 //			symbolLocation, symbolSize, symbolName);
140 		if (symbolSize > 0 && symbolType == B_SYMBOL_TYPE_TEXT) {
141 			Symbol* symbol = new(std::nothrow) Symbol(this,
142 				(addr_t)symbolLocation, symbolSize, symbolName);
143 			if (symbol == NULL || !symbols.AddItem(symbol)) {
144 				delete symbol;
145 				fprintf(stderr, "%s: Out of memory\n", kCommandName);
146 				return B_NO_MEMORY;
147 			}
148 		}
149 	}
150 
151 	// sort the symbols
152 	fSymbolCount = symbols.CountItems();
153 	fSymbols = new(std::nothrow) Symbol*[fSymbolCount];
154 	if (fSymbols == NULL)
155 		return B_NO_MEMORY;
156 
157 	for (int32 i = fSymbolCount - 1; i >= 0 ; i--)
158 		fSymbols[i] = symbols.RemoveItemAt(i);
159 
160 	std::sort(fSymbols, fSymbols + fSymbolCount, SymbolComparator());
161 
162 	return B_OK;
163 }
164