@@ -92,8 +92,6 @@ StatusOr<std::unique_ptr<DwarfReader>> DwarfReader::CreateWithoutIndexing(
9292 auto dwarf_reader = std::unique_ptr<DwarfReader>(
9393 new DwarfReader (std::move (buffer), DWARFContext::create (*obj_file)));
9494
95- PX_RETURN_IF_ERROR (dwarf_reader->DetectSourceLanguage ());
96-
9795 return dwarf_reader;
9896}
9997
@@ -154,36 +152,29 @@ bool IsNamespace(llvm::dwarf::Tag tag) { return tag == llvm::dwarf::DW_TAG_names
154152
155153} // namespace
156154
157- Status DwarfReader::DetectSourceLanguage () {
158- for (size_t i = 0 ; i < dwarf_context_->getNumCompileUnits (); ++i) {
159- const auto & unit_die = dwarf_context_->getUnitAtIndex (i)->getUnitDIE ();
160- if (unit_die.getTag () != llvm::dwarf::DW_TAG_compile_unit) {
161- // Skip over DW_TAG_partial_unit, and potentially other tags.
162- continue ;
163- }
164-
165- PX_ASSIGN_OR (const DWARFFormValue& lang_attr,
166- GetAttribute (unit_die, llvm::dwarf::DW_AT_language), continue );
167- source_language_ =
168- static_cast <llvm::dwarf::SourceLanguage>(lang_attr.getAsUnsignedConstant ().getValue ());
169-
170- const DWARFFormValue& producer_attr =
171- GetAttribute (unit_die, llvm::dwarf::DW_AT_producer).ValueOr ({});
172-
173- auto s = producer_attr.getAsCString ();
155+ StatusOr<std::pair<llvm::dwarf::SourceLanguage, std::string>>
156+ DwarfReader::DetectSourceLanguageFromCUDIE (const llvm::DWARFDie& unit_die) {
157+ if (unit_die.getTag () != llvm::dwarf::DW_TAG_compile_unit) {
158+ // Skip over DW_TAG_partial_unit, and potentially other tags.
159+ return error::NotFound (" Expected DW_TAG_compile_unit, but got DW_TAG=$0 for unit DIE: $1" ,
160+ magic_enum::enum_name (unit_die.getTag ()), Dump (unit_die));
161+ }
162+ const DWARFFormValue& producer_attr =
163+ GetAttribute (unit_die, llvm::dwarf::DW_AT_producer).ValueOr ({});
164+ auto s = producer_attr.getAsCString ();
165+ std::string compiler;
174166#if LLVM_VERSION_MAJOR >= 14
175- if (!s.takeError ()) {
176- compiler_ = s.get ();
177- }
167+ if (!s.takeError ()) {
168+ compiler = s.get ();
169+ }
178170#else
179- compiler_ = s.getValueOr (" " );
171+ compiler = s.getValueOr (" " );
180172#endif
181-
182- return Status::OK ();
183- }
184- return error::Internal (
185- " Could not determine the source language of the DWARF info. DW_AT_language not found on "
186- " any compilation unit." );
173+ PX_ASSIGN_OR_RETURN (const DWARFFormValue& lang_attr,
174+ GetAttribute (unit_die, llvm::dwarf::DW_AT_language));
175+ auto source_language =
176+ static_cast <llvm::dwarf::SourceLanguage>(lang_attr.getAsUnsignedConstant ().getValue ());
177+ return std::make_pair (source_language, compiler);
187178}
188179
189180void DwarfReader::IndexDIEs (
@@ -923,16 +914,20 @@ StatusOr<std::map<std::string, ArgInfo>> DwarfReader::GetFunctionArgInfo(
923914 // but DW_AT_location has been found to be blank in some cases, making it unreliable.
924915 // Instead, we use a FunctionArgTracker that tries to reverse engineer the calling convention.
925916
926- ABI abi = LanguageToABI (source_language_, compiler_);
917+ PX_ASSIGN_OR_RETURN (const DWARFDie& function_die,
918+ GetMatchingDIE (function_symbol_name, llvm::dwarf::DW_TAG_subprogram));
919+ // Certain binaries can have DW_TAG_compile_units with different source languages. When compiling
920+ // programs with ASAN/TSAN enabled this is common.
921+ llvm::DWARFUnit* cu = function_die.getDwarfUnit ();
922+ llvm::DWARFDie unit_die = cu->getUnitDIE ();
923+ PX_ASSIGN_OR_RETURN (auto p, DetectSourceLanguageFromCUDIE (unit_die));
924+ ABI abi = LanguageToABI (p.first , p.second );
927925 if (abi == ABI::kUnknown ) {
928926 return error::Unimplemented (" Unable to determine ABI from language: $0" ,
929- magic_enum::enum_name (source_language_ ));
927+ magic_enum::enum_name (p. first ));
930928 }
931929 std::unique_ptr<ABICallingConventionModel> arg_tracker = ABICallingConventionModel::Create (abi);
932930
933- PX_ASSIGN_OR_RETURN (const DWARFDie& function_die,
934- GetMatchingDIE (function_symbol_name, llvm::dwarf::DW_TAG_subprogram));
935-
936931 // If function has a return value, process that first.
937932 // This is important, because in some ABIs (e.g. SystemV ABI),
938933 // if the return value is not able to be passed back in the available registers,
@@ -968,7 +963,7 @@ StatusOr<std::map<std::string, ArgInfo>> DwarfReader::GetFunctionArgInfo(
968963 PX_ASSIGN_OR_RETURN (const DWARFDie type_die, GetTypeDie (die));
969964 PX_ASSIGN_OR_RETURN (arg.type_info , GetTypeInfo (die, type_die));
970965
971- if (source_language_ == llvm::dwarf::DW_LANG_Go) {
966+ if (p. first == llvm::dwarf::DW_LANG_Go) {
972967 arg.retarg = IsGolangRetArg (die).ValueOr (false );
973968 }
974969
0 commit comments