(self, name: str, is_driver: bool = False)
| 227 | self.ql.log.debug(f"Forwarding symbol {source_dll}.{source_symbol} to {target_dll}.{target_symbol}: Resolved symbol to ({forward_ea:#x})") |
| 228 | |
| 229 | def load_dll(self, name: str, is_driver: bool = False) -> int: |
| 230 | dll_path, dll_name = self.__get_path_elements(name) |
| 231 | |
| 232 | if dll_name.startswith('api-ms-win-'): |
| 233 | # Usually we should not reach this point and instead imports from such DLLs should be redirected earlier |
| 234 | self.ql.log.debug(f'Refusing to load virtual DLL {dll_name}') |
| 235 | return 0 |
| 236 | |
| 237 | # see if this dll was already loaded |
| 238 | image = self.get_image_by_name(dll_name, casefold=True) |
| 239 | |
| 240 | if image is not None: |
| 241 | return image.base |
| 242 | |
| 243 | if not os.path.exists(dll_path): |
| 244 | # posix hosts may not find the requested filename if it was saved under a different case. |
| 245 | # For example, 'KernelBase.dll' may not be found because it is stored as 'kernelbase.dll'. |
| 246 | # |
| 247 | # try to locate the requested file while ignoring the case of its path elements. |
| 248 | dll_casefold_path = self.ql.os.path.host_casefold_path(dll_path) |
| 249 | |
| 250 | if dll_casefold_path is None: |
| 251 | self.ql.log.error(f'Could not find DLL file: {dll_path}') |
| 252 | return 0 |
| 253 | |
| 254 | dll_path = dll_casefold_path |
| 255 | |
| 256 | self.ql.log.info(f'Loading {dll_name} ...') |
| 257 | |
| 258 | import_symbols = {} |
| 259 | import_table = {} |
| 260 | |
| 261 | cached = None |
| 262 | loaded = False |
| 263 | |
| 264 | if self.libcache: |
| 265 | cached = self.libcache.restore(dll_path) |
| 266 | |
| 267 | if cached: |
| 268 | data = cached.data |
| 269 | |
| 270 | image_base = cached.ba |
| 271 | image_size = self.ql.mem.align_up(len(data)) |
| 272 | |
| 273 | # verify whether we can load the dll to the same address it was loaded when it was cached. |
| 274 | # if not, the dll will have to be realoded in order to have its symbols relocated using the |
| 275 | # new address |
| 276 | if self.ql.mem.is_available(image_base, image_size): |
| 277 | import_symbols = cached.import_symbols |
| 278 | import_table = cached.import_table |
| 279 | |
| 280 | for entry in cached.cmdlines: |
| 281 | self.set_cmdline(entry['name'], entry['address'], data) |
| 282 | |
| 283 | self.ql.log.info(f'Loaded {dll_name} from cache') |
| 284 | loaded = True |
| 285 | |
| 286 | # either file was not cached, or could not be loaded to the same location in memory |
no test coverage detected