diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc index a4faab99..d129fba4 100644 --- a/src/common/dwarf_cu_to_module.cc +++ b/src/common/dwarf_cu_to_module.cc @@ -269,6 +269,9 @@ struct DwarfCUToModule::CUContext { // // Destroying this destroys all the functions this vector points to. vector functions; + + // A map of function pointers to the its forward specification DIE's offset. + map spec_function_offsets; }; // Information about the context of a particular DIE. This is for @@ -714,6 +717,9 @@ void DwarfCUToModule::FuncHandler::Finish() { cu_context_->file_context->file_private_ ->forward_ref_die_to_func[forward_ref_die_offset_] = cu_context_->functions.back(); + + cu_context_->spec_function_offsets[cu_context_->functions.back()] = + forward_ref_die_offset_; } } } else if (inline_) { @@ -1313,9 +1319,15 @@ void DwarfCUToModule::Finish() { AssignLinesToFunctions(); // Add our functions, which now have source lines assigned to them, - // to module_. - cu_context_->file_context->module_->AddFunctions(functions->begin(), - functions->end()); + // to module_, and remove duplicate functions. + for (Module::Function* func : *functions) + if (!cu_context_->file_context->module_->AddFunction(func)) { + auto iter = cu_context_->spec_function_offsets.find(func); + if (iter != cu_context_->spec_function_offsets.end()) + cu_context_->file_context->file_private_->forward_ref_die_to_func.erase( + iter->second); + delete func; + } // Ownership of the function objects has shifted from cu_context to // the Module. diff --git a/src/common/module.cc b/src/common/module.cc index f70ae203..fc85e643 100644 --- a/src/common/module.cc +++ b/src/common/module.cc @@ -80,13 +80,13 @@ void Module::SetAddressRanges(const vector& ranges) { address_ranges_ = ranges; } -void Module::AddFunction(Function* function) { +bool Module::AddFunction(Function* function) { // FUNC lines must not hold an empty name, so catch the problem early if // callers try to add one. assert(!function->name.empty()); if (!AddressIsInModule(function->address)) { - return; + return false; } // FUNCs are better than PUBLICs as they come with sizes, so remove an extern @@ -120,14 +120,9 @@ void Module::AddFunction(Function* function) { if (!ret.second && (*ret.first != function)) { // Free the duplicate that was not inserted because this Module // now owns it. - delete function; + return false; } -} - -void Module::AddFunctions(vector::iterator begin, - vector::iterator end) { - for (vector::iterator it = begin; it != end; ++it) - AddFunction(*it); + return true; } void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) { diff --git a/src/common/module.h b/src/common/module.h index 408e620b..ad282836 100644 --- a/src/common/module.h +++ b/src/common/module.h @@ -216,13 +216,8 @@ class Module { // Add FUNCTION to the module. FUNCTION's name must not be empty. // This module owns all Function objects added with this function: // destroying the module destroys them as well. - void AddFunction(Function* function); - - // Add all the functions in [BEGIN,END) to the module. - // This module owns all Function objects added with this function: - // destroying the module destroys them as well. - void AddFunctions(vector::iterator begin, - vector::iterator end); + // Return false if the function is duplicate and needs to be freed. + bool AddFunction(Function* function); // Add STACK_FRAME_ENTRY to the module. // This module owns all StackFrameEntry objects added with this diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc index 7b1b9cda..0d8aa044 100644 --- a/src/common/module_unittest.cc +++ b/src/common/module_unittest.cc @@ -265,7 +265,7 @@ TEST(Write, NoCFI) { contents.c_str()); } -TEST(Construct, AddFunctions) { +TEST(Construct, AddFunction) { stringstream s; Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); @@ -287,7 +287,8 @@ TEST(Construct, AddFunctions) { vec.push_back(function1); vec.push_back(function2); - m.AddFunctions(vec.begin(), vec.end()); + for (Module::Function* func: vec) + m.AddFunction(func); m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); diff --git a/src/common/stabs_to_module.cc b/src/common/stabs_to_module.cc index 05b25a74..dd61d4d4 100644 --- a/src/common/stabs_to_module.cc +++ b/src/common/stabs_to_module.cc @@ -192,7 +192,8 @@ void StabsToModule::Finalize() { } // Now that everything has a size, add our functions to the module, and // dispose of our private list. - module_->AddFunctions(functions_.begin(), functions_.end()); + for (Module::Function* func: functions_) + module_->AddFunction(func); functions_.clear(); }