tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / bin / debug / ltrace / ltrace_stub.cpp
blobf34949092b4f9661610745a333f20e259f7e0cad
1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
9 #include <new>
11 #include <OS.h>
13 #include <runtime_loader.h>
14 #include <util/OpenHashTable.h>
16 #include "arch/ltrace_stub.h"
19 //#define TRACE_PRINTF debug_printf
20 #define TRACE_PRINTF ktrace_printf
23 static void* function_call_callback(const void* stub, const void* args);
26 struct PatchEntry {
27 PatchEntry* originalTableLink;
28 PatchEntry* patchedTableLink;
30 void* originalFunction;
31 void* patchedFunction;
32 const char* functionName;
34 static PatchEntry* Create(const char* name, void* function)
36 void* memory = malloc(_ALIGN(sizeof(PatchEntry))
37 + arch_call_stub_size());
38 if (memory == NULL)
39 return NULL;
41 PatchEntry* entry = new(memory) PatchEntry;
43 void* stub = (uint8*)memory + _ALIGN(sizeof(PatchEntry));
44 arch_init_call_stub(stub, &function_call_callback, function);
46 entry->originalFunction = function;
47 entry->patchedFunction = stub;
48 entry->functionName = name;
50 return entry;
55 struct OriginalTableDefinition {
56 typedef const void* KeyType;
57 typedef PatchEntry ValueType;
59 size_t HashKey(const void* key) const
61 return (addr_t)key >> 2;
64 size_t Hash(PatchEntry* value) const
66 return HashKey(value->originalFunction);
69 bool Compare(const void* key, PatchEntry* value) const
71 return value->originalFunction == key;
74 PatchEntry*& GetLink(PatchEntry* value) const
76 return value->originalTableLink;
81 struct PatchedTableDefinition {
82 typedef const void* KeyType;
83 typedef PatchEntry ValueType;
85 size_t HashKey(const void* key) const
87 return (addr_t)key >> 2;
90 size_t Hash(PatchEntry* value) const
92 return HashKey(value->patchedFunction);
95 bool Compare(const void* key, PatchEntry* value) const
97 return value->patchedFunction == key;
100 PatchEntry*& GetLink(PatchEntry* value) const
102 return value->patchedTableLink;
107 static rld_export* sRuntimeLoaderInterface;
108 static runtime_loader_add_on_export* sRuntimeLoaderAddOnInterface;
110 static BOpenHashTable<OriginalTableDefinition> sOriginalTable;
111 static BOpenHashTable<PatchedTableDefinition> sPatchedTable;
114 static void*
115 function_call_callback(const void* stub, const void* _args)
117 PatchEntry* entry = sPatchedTable.Lookup(stub);
118 if (entry == NULL)
120 TRACE_PRINTF("function_call_callback(): CALLED FOR UNKNOWN FUNCTION!\n");
121 return NULL;
124 char buffer[1024];
125 size_t bufferSize = sizeof(buffer);
126 size_t written = 0;
128 const uint32* args = (const uint32*)_args;
129 written += snprintf(buffer, bufferSize, "ltrace: %s(",
130 entry->functionName);
131 for (int32 i = 0; i < 5; i++) {
132 written += snprintf(buffer + written, bufferSize - written, "%s%#lx",
133 i == 0 ? "" : ", ", args[i]);
135 written += snprintf(buffer + written, bufferSize - written, ")");
136 TRACE_PRINTF("%s\n", buffer);
138 return entry->originalFunction;
142 static void
143 symbol_patcher(void* cookie, image_t* rootImage, image_t* image,
144 const char* name, image_t** foundInImage, void** symbol, int32* type)
146 TRACE_PRINTF("symbol_patcher(%p, %p, %p, \"%s\", %p, %p, %ld)\n",
147 cookie, rootImage, image, name, *foundInImage, *symbol, *type);
149 // patch functions only
150 if (*type != B_SYMBOL_TYPE_TEXT)
151 return;
153 // already patched?
154 PatchEntry* entry = sOriginalTable.Lookup(*symbol);
155 if (entry != NULL) {
156 *foundInImage = NULL;
157 *symbol = entry->patchedFunction;
158 return;
161 entry = PatchEntry::Create(name, *symbol);
162 if (entry == NULL)
163 return;
165 sOriginalTable.Insert(entry);
166 sPatchedTable.Insert(entry);
168 TRACE_PRINTF(" -> patching to %p\n", entry->patchedFunction);
170 *foundInImage = NULL;
171 *symbol = entry->patchedFunction;
175 static void
176 ltrace_stub_init(rld_export* standardInterface,
177 runtime_loader_add_on_export* addOnInterface)
179 TRACE_PRINTF("ltrace_stub_init(%p, %p)\n", standardInterface, addOnInterface);
180 sRuntimeLoaderInterface = standardInterface;
181 sRuntimeLoaderAddOnInterface = addOnInterface;
183 sOriginalTable.Init();
184 sPatchedTable.Init();
188 static void
189 ltrace_stub_image_loaded(image_t* image)
191 TRACE_PRINTF("ltrace_stub_image_loaded(%p): \"%s\" (%ld)\n", image, image->path,
192 image->id);
194 if (sRuntimeLoaderAddOnInterface->register_undefined_symbol_patcher(image,
195 symbol_patcher, (void*)(addr_t)0xc0011eaf) != B_OK) {
196 TRACE_PRINTF(" failed to install symbol patcher\n");
201 static void
202 ltrace_stub_image_relocated(image_t* image)
204 TRACE_PRINTF("ltrace_stub_image_relocated(%p): \"%s\" (%ld)\n", image,
205 image->path, image->id);
209 static void
210 ltrace_stub_image_initialized(image_t* image)
212 TRACE_PRINTF("ltrace_stub_image_initialized(%p): \"%s\" (%ld)\n", image,
213 image->path, image->id);
217 static void
218 ltrace_stub_image_uninitializing(image_t* image)
220 TRACE_PRINTF("ltrace_stub_image_uninitializing(%p): \"%s\" (%ld)\n", image,
221 image->path, image->id);
225 static void
226 ltrace_stub_image_unloading(image_t* image)
228 TRACE_PRINTF("ltrace_stub_image_unloading(%p): \"%s\" (%ld)\n", image,
229 image->path, image->id);
233 // interface for the runtime loader
234 runtime_loader_add_on __gRuntimeLoaderAddOn = {
235 RUNTIME_LOADER_ADD_ON_VERSION, // version
236 0, // flags
238 ltrace_stub_init,
240 ltrace_stub_image_loaded,
241 ltrace_stub_image_relocated,
242 ltrace_stub_image_initialized,
243 ltrace_stub_image_uninitializing,
244 ltrace_stub_image_unloading