* Find a function from a DLL (a.k.a. GetProcAddress). */
| 320 | * Find a function from a DLL (a.k.a. GetProcAddress). |
| 321 | */ |
| 322 | static NO_INLINE const void *e9get(const uint8_t *dll, const char *target) |
| 323 | { |
| 324 | if (dll == NULL) |
| 325 | return NULL; |
| 326 | |
| 327 | uint32_t pe_offset = *(const uint32_t *)(dll + 0x3c); |
| 328 | const IMAGE_FILE_HEADER *file_hdr = |
| 329 | (PIMAGE_FILE_HEADER)(dll + pe_offset + sizeof(uint32_t)); |
| 330 | const IMAGE_OPTIONAL_HEADER64 *opt_hdr = |
| 331 | (PIMAGE_OPTIONAL_HEADER64)(file_hdr + 1); |
| 332 | const IMAGE_EXPORT_DIRECTORY *exports = (PIMAGE_EXPORT_DIRECTORY)(dll + |
| 333 | opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); |
| 334 | |
| 335 | const uint32_t *names = (uint32_t *)(dll + exports->AddressOfNames); |
| 336 | const uint32_t *funcs = (uint32_t *)(dll + exports->AddressOfFunctions); |
| 337 | uint32_t num_names = exports->NumberOfNames; |
| 338 | |
| 339 | int32_t lo = 0, hi = (int32_t)(num_names - 1); |
| 340 | while (lo <= hi) |
| 341 | { |
| 342 | int32_t mid = (lo + hi) / 2; |
| 343 | const char *name = (const char *)(dll + names[mid]); |
| 344 | int cmp = e9strcmp(target, name); |
| 345 | if (cmp < 0) |
| 346 | lo = mid + 1; |
| 347 | else if (cmp > 0) |
| 348 | hi = mid - 1; |
| 349 | else |
| 350 | return (const void *)(dll + funcs[mid]); |
| 351 | } |
| 352 | return NULL; |
| 353 | } |
| 354 | |
| 355 | /* |
| 356 | * Unlike Linux, the Windows kernel uses extended registers (%xmm, etc.), |