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