While debugging an android process remotely from a windows machine, I
noticed that the modules constructed from an object file in memory only had
information about the architecture. Without knowledge of the OS or environment,
expression evaluation sometimes leads to incorrectly generated code or a
debugger crash. While we cannot know for certain what triple a module
constructed from an in-memory object file will have, we can use the triple
from the target to try and fill in the missing details.
Details
- Reviewers
clayborg zturner JDevlieghere compnerd aprantl labath - Commits
- rGa07287ecc5e3: Merge target triple into module triple when constructing module from memory
rLLDB354526: Merge target triple into module triple when constructing module from memory
rL354526: Merge target triple into module triple when constructing module from memory
Diff Detail
- Build Status
Buildable 28294 Build 28293: arc lint + arc unit
Event Timeline
a good guess is the triple that the target executable was compiled for.
What does this do when the executable has multiple slices, such as a Mach-O universal binary?
Hmm, I hadn't considered that case. I'll test that and see what happens. Thanks for pointing that out.
source/Target/Process.cpp | ||
---|---|---|
2638–2639 | Is the MergeFrom in the first part not enough? I am worried about the case where we don't have even an executable, no one has set the architecture on the target, or worse yet, they have set the wrong architecture on the target. We want to correct the architecture on the target if we didn't specify it or the target was wrong. I am worried if we do this here we might hose up things in those cases. |
source/Target/Process.cpp | ||
---|---|---|
2638–2639 | MergeFrom is not enough. When debugging an android-aarch64 binary, the triple was just set to aarch64--- for modules constructed from in-memory object files, which is not enough info to do anything meaningful. However, thinking about this further, MergeFrom might not even be what we want here. Specifically, this is *just* a guess and the information from the in-memory object file is likely more reliable. It would probably better not to merge but to overwrite when information is available. |
source/Target/Process.cpp | ||
---|---|---|
2639 | So if you have a target that is set to "aarch64-linux-android', and you have "aarch64---" in your object file/module, you would want to merge the missing bits from the target to augment the module's architecture so it grabs the "linux-android" bits. So I do believe MergeFrom should be used to augment the Module's architecture. |
source/Target/Process.cpp | ||
---|---|---|
2639 | Ah, yes! Merging from the other direction is definitely what I wanted. Thanks for pointing that out. |
Probably just a replay of GDB protocol packets connected to a testing server would work. But, I don't know if there is infrastructure for that yet.
Augmenting the architecture with the target information sounds right to me. If we're reading a module from memory, then we already have a running target, and I consider that information more reliable (since it comes from os/lldb-server) than the object file architecture (which is just random bits in process memory). I might even go so far as to say that if we detect that the module and target ArchSpecs substantially differ (for some meaning of "substantially"), we should reject the attempt to create the module in the first place. Maybe we even do that already at some level?
Unfortunately, I think testing this is going to be hard. The infrastructure for testing in-memory object files is very under-developed. I think the best attempt would be to have a test program which creates some object files in memory (via llvm jit, or perhaps by loading pre-prepared binaries from disk), and then using the gdb jit interface to notify lldb about it. But I don't think we have anything similar to this currently.
I don't think this should be an issue since a Module object always points to a specific slice in the fat binary.
Is the MergeFrom in the first part not enough? I am worried about the case where we don't have even an executable, no one has set the architecture on the target, or worse yet, they have set the wrong architecture on the target. We want to correct the architecture on the target if we didn't specify it or the target was wrong. I am worried if we do this here we might hose up things in those cases.