This is an archive of the discontinued LLVM Phabricator instance.

[LLD][Debuginfo] create DWARFContext only once for the same object file.
ClosedPublic

Authored by avl on Feb 18 2020, 7:44 AM.

Details

Summary

LLD already has a mechanism for caching creation of DWARCContext:

llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });

Though it is not used in all places.

I need that patch for implementing "Remove obsolete debug info" feature
(D74169). But this caching mechanism is useful by itself, and I think it
would be good to use it without connection to "Remove obsolete debug info"
feature. So this patch changes inplace creation of DWARFContext with
its cached version.

Additionally, that patch makes that RecoverableErrors would not be fatal
errors. i.e., If some RecoverableErrors occurred while parsing Debug Info,
LLD would still return 0.

Depends on D74308

Diff Detail

Event Timeline

avl created this revision.Feb 18 2020, 7:44 AM
grimar added inline comments.Feb 19 2020, 12:03 AM
lld/ELF/InputFiles.cpp
269

Lets also see what other LLD people think, but it does not feel to me that LLD should get something like "recoverable error" concept.
We already have warnings to report something not critical, so why not just report a warning in this case?

avl marked an inline comment as done.Feb 19 2020, 1:08 AM
avl added inline comments.
lld/ELF/InputFiles.cpp
269

The reason for reporting this as error is to have matching output with default DebugInfoDWARF output. i.e. when DebugInfoDWARF used in other context it would report this as "error". It could look a bit inconsistent when the same problem would be reported as "warning" from LLD context. If that is not important - then we could report it as warning and do not introduce "recoverable error" concept.

MaskRay added inline comments.Feb 19 2020, 11:05 AM
lld/ELF/InputFiles.cpp
269

I recall @ruiu mentioned that we don't want "recoverable error", but I can't find the thread.

avl marked an inline comment as done.Feb 19 2020, 12:10 PM
avl added inline comments.
lld/ELF/InputFiles.cpp
269

Ok, I would change it to warning then.

avl updated this revision to Diff 245619.Feb 20 2020, 4:41 AM

fix lit-test failure, use "warning" instead of "recoverable error"

avl added a comment.Feb 20 2020, 5:06 AM

reported failures do not seem related to my patch.

jhenderson added inline comments.Feb 24 2020, 5:39 AM
lld/ELF/SyntheticSections.cpp
2677

Seems like a not-really-related change? It's certainly not NFC.

2682

Ditto.

avl marked an inline comment as done.Feb 24 2020, 7:40 AM
avl added inline comments.
lld/ELF/SyntheticSections.cpp
2677

During this review, it was suggested that debuginfo errors would be reported as warnings, when in lld context. Thus, I set warning handler for DWARFContext _and_ patched related places in lld.

originally it was NFC, but yes, now it is not NFC. Would change patch header, thanks.

avl retitled this revision from [LLD][Debuginfo][NFC] create DWARFContext only once for the same object file. to [LLD][Debuginfo] create DWARFContext only once for the same object file..Feb 24 2020, 7:41 AM

This changes looks fine, though I have a question about a regex use.

lld/test/ELF/gdb-index-parse-fail.s
5

Why did the debug_info regex become complex now?

ruiu added inline comments.Feb 24 2020, 6:43 PM
lld/ELF/InputFiles.cpp
269

Err -> err

270

Warning -> warning

307

Calling call_once from multiple places doesn't seem to be a very good way to manage object instantiation. How about this?

  • Define getDwarf() function that returns a DWARFCache object. That function initializes Dwarf member if it is not initialized yet
  • Remove initializeDwarf (since now getDwarf initializes the Dwarf member)
  • Remove getDWARFContext and rewrite getDWARFContext() with getDwarf()->getContext()
avl marked an inline comment as done.Feb 25 2020, 2:53 AM
avl added inline comments.
lld/test/ELF/gdb-index-parse-fail.s
5

Without this patch the error was reported from lld/ELF/SyntheticSections.cpp :

if (Error e = cu->tryExtractDIEsIfNeeded(false)) {
  error(toString(sec) + ": " + toString(std::move(e)));
}

lld knows the section name and prints it in error message :

ld.lld: error: gdb-index-parse-fail.s.tmp1.o:(.debug_info): invalid reference to or invalid content in .debug_str_offsets[.dwo]: insufficient space for 32 bit header prefix

With this patch the error could be reported not from lld/ELF/SyntheticSections.cpp but from DWARFUnit.cpp, using error handler provided to DWARFContext in InputFiles.cpp:

[&](Error Err) { warn(getName() + ": " + toString(std::move(Err))); }

In that case section name is not printed(DWARFUnit.cpp does not print section name). So the error looks like this(without section name):

ld.lld: error: gdb-index-parse-fail.s.tmp1.o: invalid reference to or invalid content in .debug_str_offsets[.dwo]: insufficient space for 32 bit header prefix

Thus regex become more comlpex to accept both variants: with/without section name.

avl marked an inline comment as done.Feb 25 2020, 8:29 AM
avl added inline comments.
lld/ELF/InputFiles.cpp
307

Just to make things clear - call_once would still be used. But it would be used in single place - inside getDwarf() function - right?

jhenderson added inline comments.Feb 26 2020, 7:32 AM
lld/ELF/SyntheticSections.cpp
2677

Okay. Seems like it should be a separate change though (i.e. one for the DWARFContext call_once stuff, and the other for error->warn).

avl updated this revision to Diff 247446.Feb 29 2020, 8:26 AM

addressed comments.

ruiu added inline comments.Mar 3 2020, 10:33 PM
lld/ELF/InputFiles.cpp
269

make is an lld's way of memory management, and I don't think you need to change this, so replace std::make_unique<DWARFCache> with make<DWARFCache>.

lld/ELF/InputFiles.h
288–289

I think you don't need to change this line

avl marked an inline comment as done.Mar 4 2020, 9:07 AM
avl added inline comments.
lld/ELF/InputFiles.cpp
269

Right. But in this concrete case, there is a memory error because of data inter-dependency(if "make" is used).

The problem that DWARFCache::variableLoc references sections which are deleted first:

DWARFCache {

llvm::DenseMap<StringRef, VarLoc> variableLoc;
}

variableLoc has StringRef as a key which uses data from corresponding InputSection.

When destructor of llvm::DenseMap is called, it checks some keys.
But since data referenced by key are already deleted, there is a memory error.
The problem is that InputSections are already deallocated at this time.

freeArena() function starts from the first allocated object and goes till the last allocated object.
DWARFCache was allocated after InputSections.
Thus, when ~DWARFCache() is called - the sections, it references to, are already deleted.

To avoid that problem, I used std::unique_ptr for DWARFCache so that it would be deleted from the destructor of ObjFile. ObjFile is allocated before InputSections.
As a result, ~DWARFCache() is called first, and the problem does not happen.

ruiu accepted this revision.Mar 5 2020, 11:23 PM

LGTM

This revision is now accepted and ready to land.Mar 5 2020, 11:23 PM
This revision was automatically updated to reflect the committed changes.
MaskRay added a comment.EditedMar 12 2020, 5:03 PM

Commit dcf6494abed7550fc84d6b59b33efc634a95c1fe does not have a subject line.

See my inline comment: I am a bit concerned if we cache DWARFContext for every input file for the proposed --gc-debuginfo feature.

For that affected internal target (which uses --gdb-index):

% /usr/bin/time -f "%P %M" /tmp/ReleaseA/bin/ld.lld @response.txt --no-gdb-index
546% 13761460

# Between D74773 and my fix
% /usr/bin/time -f "%P %M" /tmp/ReleaseA/bin/ld.lld @response.txt
1010% 22083732

# Before D74773 or after my fix
% /usr/bin/time -f "%P %M" /tmp/ReleaseA/bin/ld.lld @response.txt
1098% 18219472

% /usr/bin/time -f "%P %M" gold @response.txt
99% 16236236
lld/ELF/SyntheticSections.cpp
2825

We don't want to keep cached DWARFContext here.

--gdb-index can be memory heavy and caching DWARFContext for every input section can greatly increase memory usage.

I have fixed it (restored the previous behavior) with commit 0bb362c1649912d3a328dd01c700626d0a9f5a2c.