Files
nerix 44fefe70e4 [LLDB][NativePDB] Estimate symbol sizes (#165727)
In #165604, a test was skipped on Windows, because the native PDB plugin
didn't set sizes on symbols. While the test isn't compiled with debug
info, it's linked with `-gdwarf`, causing a PDB to be created on
Windows. This PDB will only contain the public symbols (written by the
linker) and section information. The symbols themselves don't have a
size, however the DIA SDK sets a size for them.
It seems like, for these data symbols, the size given from DIA is the
distance to the next symbol (or the section end).

This PR implements the naive approach for the native plugin. The main
difference is in function/code symbols. There, DIA searches for a
corresponding `S_GPROC32` which have a "code size" that is sometimes
slightly smaller than the difference to the next symbol.
2025-10-31 10:33:37 +01:00

111 lines
4.3 KiB
Python

"""
Test that a binary can be slid to different load addresses correctly
"""
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class MultipleSlidesTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def test_mulitple_slides(self):
"""Test that a binary can be slid multiple times correctly."""
self.build()
exe = self.getBuildArtifact("a.out")
err = lldb.SBError()
load_dependent_modules = False
target = self.dbg.CreateTarget(exe, "", "", load_dependent_modules, err)
self.assertTrue(target.IsValid())
module = target.GetModuleAtIndex(0)
self.assertTrue(module.IsValid())
first_sym = target.FindSymbols("first").GetContextAtIndex(0).GetSymbol()
second_sym = target.FindSymbols("second").GetContextAtIndex(0).GetSymbol()
first_size = (
first_sym.GetEndAddress().GetOffset()
- first_sym.GetStartAddress().GetOffset()
)
int_size = target.FindFirstType("int").GetByteSize()
self.assertGreaterEqual(first_size, 2048 * int_size)
second_size = (
second_sym.GetEndAddress().GetOffset()
- second_sym.GetStartAddress().GetOffset()
)
self.assertGreaterEqual(second_size, 2048 * int_size)
# View the first element of `first` and `second` while
# they have no load address set.
self.expect("expression/d ((int*)&first)[0]", substrs=["= 5"])
self.expect("expression/d ((int*)&second)[0]", substrs=["= 6"])
self.assertEqual(
first_sym.GetStartAddress().GetLoadAddress(target),
lldb.LLDB_INVALID_ADDRESS,
)
self.assertEqual(
second_sym.GetStartAddress().GetLoadAddress(target),
lldb.LLDB_INVALID_ADDRESS,
)
# View the first element of `first` and `second` with
# no slide applied, but with load address set.
#
# In memory, we have something like
# 0x1000 - 0x17ff first[]
# 0x1800 - 0x1fff second[]
error = target.SetModuleLoadAddress(module, 0)
self.assertSuccess(error)
self.expect("expression/d ((int*)&first)[0]", substrs=["= 5"])
self.expect("expression/d ((int*)&second)[0]", substrs=["= 6"])
self.assertEqual(
first_sym.GetStartAddress().GetLoadAddress(target),
first_sym.GetStartAddress().GetFileAddress(),
)
self.assertEqual(
second_sym.GetStartAddress().GetLoadAddress(target),
second_sym.GetStartAddress().GetFileAddress(),
)
# Slide it a little bit less than the size of the first array.
#
# In memory, we have something like
# 0xfc0 - 0x17bf first[]
# 0x17c0 - 0x1fbf second[]
#
# but if the original entries are still present in lldb,
# the beginning address of second[] will get a load address
# of 0x1800, instead of 0x17c0 (0x1800-64) as we need to get.
error = target.SetModuleLoadAddress(module, first_size - 64)
self.assertSuccess(error)
self.expect("expression/d ((int*)&first)[0]", substrs=["= 5"])
self.expect("expression/d ((int*)&second)[0]", substrs=["= 6"])
self.assertNotEqual(
first_sym.GetStartAddress().GetLoadAddress(target),
first_sym.GetStartAddress().GetFileAddress(),
)
self.assertNotEqual(
second_sym.GetStartAddress().GetLoadAddress(target),
second_sym.GetStartAddress().GetFileAddress(),
)
# Slide it back to the original vmaddr.
error = target.SetModuleLoadAddress(module, 0)
self.assertSuccess(error)
self.expect("expression/d ((int*)&first)[0]", substrs=["= 5"])
self.expect("expression/d ((int*)&second)[0]", substrs=["= 6"])
self.assertEqual(
first_sym.GetStartAddress().GetLoadAddress(target),
first_sym.GetStartAddress().GetFileAddress(),
)
self.assertEqual(
second_sym.GetStartAddress().GetLoadAddress(target),
second_sym.GetStartAddress().GetFileAddress(),
)
# Make sure we can use a slide > INT64_MAX.
error = target.SetModuleLoadAddress(module, 0xFFFFFFFF12345678)
self.assertSuccess(error)