| 193 | } |
| 194 | |
| 195 | AbstractUnwinder::StatusCode |
| 196 | AbstractUnwinder::gatherInlineFrames( |
| 197 | std::vector<NativeFrame>& native_frames, |
| 198 | const std::string& noninline_symname, |
| 199 | Dwarf_Addr pc, |
| 200 | Dwarf_Addr pc_corrected, |
| 201 | Dwarf_Die* cudie, |
| 202 | const char* mod_name) const |
| 203 | { |
| 204 | // Gather initial source information . The inline functions are chained in a |
| 205 | // way that the symbol corresponding for a given scope represent the call that |
| 206 | // is happening at that scope, which means that for retrieving the file name |
| 207 | // and the source, we need to look at the previous scope, which is where the |
| 208 | // call happened. The initial source information can be obtained from the |
| 209 | // compilation unit itself. |
| 210 | |
| 211 | LOG(DEBUG) << std::hex << std::showbase << "Gathering inline frames for frame @ " << pc; |
| 212 | |
| 213 | auto srcloc = dwarf_getsrc_die(cudie, pc_corrected); |
| 214 | if (!srcloc) { |
| 215 | LOG(DEBUG) << std::hex << std::showbase << "Could not find main source information for PC @ " |
| 216 | << pc; |
| 217 | LOG(DEBUG) << "Found non-inline call without source information: " << noninline_symname; |
| 218 | native_frames.push_back({pc, demangleSymbol(noninline_symname), "???", 0, 0, mod_name}); |
| 219 | return StatusCode::ERROR; |
| 220 | } |
| 221 | |
| 222 | const char* filename = nullptr; |
| 223 | filename = dwarf_linesrc(srcloc, nullptr, nullptr); |
| 224 | if (filename == nullptr) { |
| 225 | filename = "???"; |
| 226 | } |
| 227 | int line = 0; |
| 228 | int col = 0; |
| 229 | dwarf_lineno(srcloc, &line); |
| 230 | dwarf_linecol(srcloc, &col); |
| 231 | |
| 232 | // Gather scope information for the given compilation unit |
| 233 | const ScopesInfo cudie_scopes_info = dwarfGetScopes(cudie, pc_corrected); |
| 234 | int ncudie_scopes = cudie_scopes_info.first; |
| 235 | if (ncudie_scopes == 0) { |
| 236 | LOG(DEBUG) << std::hex << std::showbase << "No inline scopes found for PC @ " << pc; |
| 237 | } else { |
| 238 | const Scopes& cudie_scopes = cudie_scopes_info.second; |
| 239 | const ScopesInfo scopes_info = dwarfGetScopesDie(cudie_scopes.get()); |
| 240 | int nscopes = scopes_info.first; |
| 241 | const Scopes& scopes = scopes_info.second; |
| 242 | |
| 243 | // Resolve all the inline frames in the obtained scopes |
| 244 | |
| 245 | for (int i = 0; i < nscopes; ++i) { |
| 246 | Dwarf_Die* scope = &scopes.get()[i]; |
| 247 | if (dwarf_tag(scope) != DW_TAG_inlined_subroutine) { |
| 248 | continue; |
| 249 | } |
| 250 | const std::optional<std::string> inlined_symname = DIENameFromScope(scope); |
| 251 | if (!inlined_symname) { |
| 252 | LOG(DEBUG) << "Scope with invalid name found @: " << scope->addr; |
nothing calls this directly
no test coverage detected