2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
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
);
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());
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
;
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
;
115 function_call_callback(const void* stub
, const void* _args
)
117 PatchEntry
* entry
= sPatchedTable
.Lookup(stub
);
120 TRACE_PRINTF("function_call_callback(): CALLED FOR UNKNOWN FUNCTION!\n");
125 size_t bufferSize
= sizeof(buffer
);
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
;
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
)
154 PatchEntry
* entry
= sOriginalTable
.Lookup(*symbol
);
156 *foundInImage
= NULL
;
157 *symbol
= entry
->patchedFunction
;
161 entry
= PatchEntry::Create(name
, *symbol
);
165 sOriginalTable
.Insert(entry
);
166 sPatchedTable
.Insert(entry
);
168 TRACE_PRINTF(" -> patching to %p\n", entry
->patchedFunction
);
170 *foundInImage
= NULL
;
171 *symbol
= entry
->patchedFunction
;
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();
189 ltrace_stub_image_loaded(image_t
* image
)
191 TRACE_PRINTF("ltrace_stub_image_loaded(%p): \"%s\" (%ld)\n", image
, image
->path
,
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");
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
);
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
);
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
);
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
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