Skip to content

Commit

Permalink
[lldb] On POSIX, check for duplicate interpreter modules without load…
Browse files Browse the repository at this point in the history
…ing them (#69932)

Fixes #68987

Early on we load the interpreter (most commonly ld-linux) in
LoadInterpreterModule. Then later when we get the first DYLD rendezvous
we get a list of libraries that commonly includes ld-linux again.

Previously we would load this duplicate, see that it was a duplicate,
and unload it.

Problem was that this unloaded the section information of the first copy
of ld-linux. On platforms where you can place a breakpoint using only an
address, this wasn't an issue.

On ARM you have ARM and Thumb modes. We must know which one the section
we're breaking in is, otherwise we'll go there in the wrong mode and
SIGILL. This happened on ARM when lldb tried to call mmap during
expression evaluation.

To fix this, I am making the assumption that the base address we see in
the module prior to loading can be compared with what we know the
interpreter base address is. Then we don't have to load the module to
know we can ignore it.

This fixes the lldb test suite on Ubuntu versions where
https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/1927192 has been
fixed. Which was recently done on Jammy.
  • Loading branch information
DavidSpickett committed Oct 25, 2023
1 parent e7012ba commit ff67b68
Showing 1 changed file with 8 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,14 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() {
m_initial_modules_added = true;
}
for (; I != E; ++I) {
// Don't load a duplicate copy of ld.so if we have already loaded it
// earlier in LoadInterpreterModule. If we instead loaded then unloaded it
// later, the section information for ld.so would be removed. That
// information is required for placing breakpoints on Arm/Thumb systems.
if ((m_interpreter_module.lock() != nullptr) &&
(I->base_addr == m_interpreter_base))
continue;

ModuleSP module_sp =
LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (!module_sp.get())
Expand All @@ -450,15 +458,6 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() {
} else if (module_sp == interpreter_sp) {
// Module already loaded.
continue;
} else {
// If this is a duplicate instance of ld.so, unload it. We may end
// up with it if we load it via a different path than before
// (symlink vs real path).
// TODO: remove this once we either fix library matching or avoid
// loading the interpreter when setting the rendezvous breakpoint.
UnloadSections(module_sp);
loaded_modules.Remove(module_sp);
continue;
}
}

Expand Down

0 comments on commit ff67b68

Please sign in to comment.