This is an archive of the discontinued LLVM Phabricator instance.

Use the UUID from the minidump's CodeView Record for placeholder modules
ClosedPublic

Authored by lemo on Apr 30 2018, 3:22 PM.

Details

Summary

This change adds support for two types of Minidump CodeView records:

  1. PDB70 (reference: https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html)

This is by far the most common record type.

  1. ELF BuildID (found in Breakpad/Crashpad generated minidumps)

This would set a proper UUID for placeholder modules, in turn enabling an accurate match with local module images.

Diff Detail

Repository
rL LLVM

Event Timeline

lemo created this revision.Apr 30 2018, 3:22 PM
amccarth accepted this revision.Apr 30 2018, 3:52 PM

The big picture here is fine.

I see a couple opportunities in the details, but I won't block on them.

include/lldb/Core/Module.h
779 ↗(On Diff #144644)

Was there no SetUUID before because the UUID was considered immutable? I wonder if that's worth keeping. Is the UUID always known at construction time?

source/Core/Module.cpp
341 ↗(On Diff #144644)

I wonder if the lazy UUID lookup in Module::GetUUID should call this to avoid code duplication. I know it's not a lot of code, but it involves a mutex and an atomic flag, so it might be nice to always have this update in just one place.

source/Plugins/Process/minidump/MinidumpParser.cpp
99 ↗(On Diff #144644)

I wonder if this should return an Expected<UUID>. The function has multiple ways it can fail, in which case the error info is lost and we silently return an empty UUID.

This revision is now accepted and ready to land.Apr 30 2018, 3:52 PM
labath added inline comments.May 1 2018, 1:40 AM
include/lldb/Core/Module.h
779 ↗(On Diff #144644)

The UUID is not always know at construction time -- sometimes it can be, if you set it on the FileSpec you use to create the module, but you don't have to do that.

However, it is true that the UUID was constant during the lifetime of the Module, and this changes that, which is not ideal IMO.

It seems that in the only place you call this function, you already know the UUID. Would it be possible to do this work in the PlaceholderModule constructor (thereby avoiding any changes to the Module API) ?

source/Plugins/Process/minidump/MinidumpParser.cpp
118–128 ↗(On Diff #144644)

Looks like the elf part of this is not tested. Do any of our linux minidumps have a build-id we could use?

Since the parser->SB path is already tested by the windows test, this doesn't have to be a full-blown test and a minidump parser unittest (unittests/Process/minidump) should be sufficient.

lemo updated this revision to Diff 144751.May 1 2018, 10:59 AM
lemo marked 5 inline comments as done.

Thanks for the feedback. I uploaded a new revision (incorporating some of the feedback, including an ELF test case)

include/lldb/Core/Module.h
779 ↗(On Diff #144644)

Good point: I agree, it's a good idea to preserve the invariant that the module UUID does not change once it's set.

I'd not add more complexity & arguments to the placeholder module constructor though. Moreover, even if it's technically possible to reach into the protected data members from Module I'd like to avoid doing that since Module::m_uuid is closely tied to Module::m_mutex and Module::m_did_parse_uuid (the later now renamed to m_did_set_uuid).

I added a check and assert to prevent Module::SetUUID from overwriting an already set UUID. (Personally I'd would've liked to have the assert be a fastfail in all builds but I remember that is somewhat against the LLDB philosophy)

source/Core/Module.cpp
341 ↗(On Diff #144644)

Good point, but I'm afraid that would obscure the double-checked-locking in Module::GetUUID() so I'd rather not change it.

source/Plugins/Process/minidump/MinidumpParser.cpp
99 ↗(On Diff #144644)

The goal is support the common CV records we expect to see from current toolchains and the contract for GetModuleUUID() is to either return a valid UUID or an empty one.

Neither is an error: the CV record is optional and we also can't guarantee to handle every single CV record type.

labath added inline comments.May 1 2018, 12:16 PM
include/lldb/Core/Module.h
779 ↗(On Diff #144644)

Guarding the invariant with an assert is better than nothing, but even better is arranging stuff so that the invariant cannot be broken in the first place. And this feels like the sort of thing that should be possible to make safe by design.

How about adding a special (protected?) Module constructor, which takes a UUID argument and uses it to initialize the m_uuid field. This way, it is impossible by design to change the UUID mid-flight, and you still don't have to reach into the protected Module fields from the other class (we could even make them private if we want to).

lemo updated this revision to Diff 144790.May 1 2018, 2:34 PM
lemo added inline comments.
include/lldb/Core/Module.h
779 ↗(On Diff #144644)

Trying to make sure that the invariant can't be invalidated is a high bar considering that most Module state is protected. But I agree with the sentiment and here's a new iteration:

  1. Made Module::SetUUID() protected (note that the m_uuid change is conditional, not just protected by an lldbassert)
  2. PlaceholderModule constructor is where SetUUID is called from

I'm hesitant to add another Module constructor: that class already has 2 public + 1 private constructors (even using a delegating constructor, the addition of a new protected constructor questionable). But if you still prefer that option better I'll make the change.

labath accepted this revision.May 2 2018, 6:12 AM

I think this is fine. I would have preferred a constructor solution, but the situation there does appear to be a bit messy. I like how you were able to place the SetUUID method next to SetArchitecture. Thanks for your patience.

source/Commands/CommandObjectTarget.cpp
1390 ↗(On Diff #144790)

strm.Format("No object file for module: {0:F}\n", module->GetFileSpec()) should hopefully fit on a single line

lemo marked an inline comment as done.May 2 2018, 10:18 AM
lemo added inline comments.
source/Commands/CommandObjectTarget.cpp
1390 ↗(On Diff #144790)

It does not fit on a single line, but it's cleaner - done, thanks for suggesting it!

This revision was automatically updated to reflect the committed changes.
lemo marked an inline comment as done.