| 120 | } |
| 121 | |
| 122 | void WinUnwindGenerator::OnModuleInstrumented(ModuleInfo* module) { |
| 123 | if (tinydbr_.child_ptr_size == 4) { |
| 124 | FATAL("-generate_unwind is unneeded (and thus incompatible) with 32-bit targets"); |
| 125 | } |
| 126 | |
| 127 | WinUnwindData* unwind_data = new WinUnwindData; |
| 128 | module->unwind_data = unwind_data; |
| 129 | |
| 130 | // read the entire image |
| 131 | // TODO (ifratric) can this fail for some modules? |
| 132 | size_t image_size = module->max_address - module->min_address; |
| 133 | BYTE* modulebuf = (BYTE*)malloc(image_size); |
| 134 | tinydbr_.RemoteRead((void *)module->min_address, modulebuf, image_size); |
| 135 | |
| 136 | DWORD exception_table_offset; |
| 137 | DWORD exception_table_size; |
| 138 | if (!GetExceptionTableOffsetAndSize((char*)modulebuf, |
| 139 | (uint32_t*)&exception_table_offset, |
| 140 | (uint32_t*)&exception_table_size)) |
| 141 | { |
| 142 | FATAL("Error getting exception table"); |
| 143 | } |
| 144 | if ((size_t)exception_table_offset + exception_table_size > image_size) { |
| 145 | FATAL("Exception table out of bounds"); |
| 146 | } |
| 147 | if (exception_table_size % (3 * sizeof(DWORD))) { |
| 148 | FATAL("Incorrect exception table format?"); |
| 149 | } |
| 150 | |
| 151 | DWORD* exception_table = (DWORD*)(modulebuf + exception_table_offset); |
| 152 | DWORD* exception_table_end = (DWORD*)(modulebuf + exception_table_offset + exception_table_size); |
| 153 | |
| 154 | DWORD function_start; |
| 155 | DWORD function_end; |
| 156 | DWORD unwind_info_offset; |
| 157 | |
| 158 | while (exception_table < exception_table_end) { |
| 159 | size_t function_info_addr = module->min_address + ((BYTE *)exception_table - modulebuf); |
| 160 | |
| 161 | function_start = *exception_table; exception_table++; |
| 162 | function_end = *exception_table; exception_table++; |
| 163 | unwind_info_offset = *exception_table; exception_table++; |
| 164 | |
| 165 | if (function_start >= function_end) continue; |
| 166 | |
| 167 | UnwindInfo* unwind_info = ReadUnwindInfo(module, modulebuf, image_size, unwind_info_offset); |
| 168 | |
| 169 | FunctionInfo *new_info = new FunctionInfo; |
| 170 | |
| 171 | new_info->function_start = module->min_address + function_start; |
| 172 | new_info->function_end = module->min_address + function_end; |
| 173 | |
| 174 | new_info->function_info_addr = function_info_addr; |
| 175 | |
| 176 | new_info->unwind_info = unwind_info; |
| 177 | |
| 178 | unwind_data->original_function_infos.push_back(new_info); |
| 179 | } |
nothing calls this directly
no test coverage detected