mirror of
https://github.com/wolfpld/tracy.git
synced 2026-10-23 17:20:48 +00:00
Merge pull request #1414 from YaLTeR/fix-elf-symbols
Fix image and symbol resolution on AerynOS and elsewhere
This commit is contained in:
@@ -237,9 +237,18 @@ private:
|
||||
if( cache->ContainsImage( startAddress ) ) return 0;
|
||||
|
||||
const uint32_t headerCount = info->dlpi_phnum;
|
||||
assert( headerCount > 0);
|
||||
const auto endAddress = static_cast<uint64_t>( info->dlpi_addr +
|
||||
info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz);
|
||||
assert( headerCount > 0 );
|
||||
|
||||
// headers aren't guaranteed to be in address order; find the max
|
||||
uint64_t endAddress = startAddress;
|
||||
for( uint32_t i=0; i<headerCount; i++ )
|
||||
{
|
||||
const auto& phdr = info->dlpi_phdr[i];
|
||||
if( phdr.p_type != PT_LOAD ) continue;
|
||||
|
||||
const auto phdrEnd = static_cast<uint64_t>( info->dlpi_addr + phdr.p_vaddr + phdr.p_memsz );
|
||||
endAddress = std::max( phdrEnd, endAddress );
|
||||
}
|
||||
|
||||
ImageEntry image{};
|
||||
image.m_startAddress = startAddress;
|
||||
|
||||
@@ -4356,15 +4356,17 @@ elf_zstd_unpack_seq_decode (int mode,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decompress a zstd stream from PIN/SIN to POUT/SOUT. Code based on RFC 8878.
|
||||
/* Decompress a single zstd frame from *PPIN, ending at PINEND, to *PPOUT/SOUT.
|
||||
Return 1 on success, 0 on error. */
|
||||
|
||||
static int
|
||||
elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
unsigned char *zdebug_table, unsigned char *pout,
|
||||
size_t sout)
|
||||
elf_zstd_decompress_frame (const unsigned char **ppin,
|
||||
const unsigned char *pinend,
|
||||
unsigned char *zdebug_table, unsigned char **ppout,
|
||||
size_t sout)
|
||||
{
|
||||
const unsigned char *pinend;
|
||||
const unsigned char *pin;
|
||||
unsigned char *pout;
|
||||
unsigned char *poutstart;
|
||||
unsigned char *poutend;
|
||||
struct elf_zstd_seq_decode literal_decode;
|
||||
@@ -4380,13 +4382,14 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
uint32_t repeated_offset3;
|
||||
uint16_t *scratch;
|
||||
unsigned char hdr;
|
||||
int single_segment;
|
||||
int has_checksum;
|
||||
uint64_t content_size;
|
||||
int last_block;
|
||||
|
||||
pinend = pin + sin;
|
||||
pin = *ppin;
|
||||
pout = *ppout;
|
||||
poutstart = pout;
|
||||
poutend = pout + sout;
|
||||
|
||||
literal_decode.table = NULL;
|
||||
literal_decode.table_bits = -1;
|
||||
@@ -4412,7 +4415,7 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
repeated_offset2 = 4;
|
||||
repeated_offset3 = 8;
|
||||
|
||||
if (unlikely (sin < 4))
|
||||
if (unlikely (pinend - pin < 4))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
@@ -4438,12 +4441,18 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
|
||||
hdr = *pin++;
|
||||
|
||||
/* We expect a single frame. */
|
||||
if (unlikely ((hdr & (1 << 5)) == 0))
|
||||
single_segment = (hdr & (1 << 5)) != 0;
|
||||
if (!single_segment)
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
if (unlikely (pin >= pinend))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
/* skip Window_Descriptor */
|
||||
pin++;
|
||||
}
|
||||
|
||||
/* Reserved bit must be zero. */
|
||||
if (unlikely ((hdr & (1 << 3)) != 0))
|
||||
{
|
||||
@@ -4460,13 +4469,22 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
switch (hdr >> 6)
|
||||
{
|
||||
case 0:
|
||||
if (unlikely (pin >= pinend))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
content_size = (uint64_t) *pin++;
|
||||
break;
|
||||
if (single_segment)
|
||||
{
|
||||
if (unlikely (pin >= pinend))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
content_size = (uint64_t) *pin++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no Frame_Content_Size; use the remaining size as the upper bound */
|
||||
content_size = (uint64_t) sout;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
if (unlikely (pin + 1 >= pinend))
|
||||
{
|
||||
@@ -4510,12 +4528,14 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
}
|
||||
|
||||
if (unlikely (content_size != (size_t) content_size
|
||||
|| (size_t) content_size != sout))
|
||||
|| (size_t) content_size > sout))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
poutend = pout + content_size;
|
||||
|
||||
last_block = 0;
|
||||
while (!last_block)
|
||||
{
|
||||
@@ -4634,6 +4654,11 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
pin += 2;
|
||||
}
|
||||
|
||||
pback = NULL;
|
||||
bits = 0;
|
||||
literal_state = 0;
|
||||
offset_state = 0;
|
||||
match_state = 0;
|
||||
if (seq_count > 0)
|
||||
{
|
||||
int (*pfn)(const struct elf_zstd_fse_entry *,
|
||||
@@ -4673,28 +4698,28 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
match_fse_table, 9, pfn,
|
||||
&match_decode))
|
||||
return 0;
|
||||
|
||||
pback = pblockend - 1;
|
||||
if (!elf_fetch_backward_init (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
|
||||
bits -= literal_decode.table_bits;
|
||||
literal_state = ((val >> bits)
|
||||
& ((1U << literal_decode.table_bits) - 1));
|
||||
|
||||
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
bits -= offset_decode.table_bits;
|
||||
offset_state = ((val >> bits)
|
||||
& ((1U << offset_decode.table_bits) - 1));
|
||||
|
||||
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
bits -= match_decode.table_bits;
|
||||
match_state = ((val >> bits)
|
||||
& ((1U << match_decode.table_bits) - 1));
|
||||
}
|
||||
|
||||
pback = pblockend - 1;
|
||||
if (!elf_fetch_backward_init (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
|
||||
bits -= literal_decode.table_bits;
|
||||
literal_state = ((val >> bits)
|
||||
& ((1U << literal_decode.table_bits) - 1));
|
||||
|
||||
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
bits -= offset_decode.table_bits;
|
||||
offset_state = ((val >> bits)
|
||||
& ((1U << offset_decode.table_bits) - 1));
|
||||
|
||||
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
|
||||
return 0;
|
||||
bits -= match_decode.table_bits;
|
||||
match_state = ((val >> bits)
|
||||
& ((1U << match_decode.table_bits) - 1));
|
||||
|
||||
seq = 0;
|
||||
while (1)
|
||||
{
|
||||
@@ -4715,6 +4740,40 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
uint32_t need;
|
||||
uint32_t add;
|
||||
|
||||
if (unlikely (seq >= seq_count))
|
||||
{
|
||||
/* Copy remaining literals. */
|
||||
if (literal_count > 0 && plit != pout)
|
||||
{
|
||||
if (unlikely ((size_t)(poutend - pout)
|
||||
< literal_count))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t)(plit - pout) < literal_count)
|
||||
{
|
||||
uint32_t move;
|
||||
|
||||
move = plit - pout;
|
||||
while (literal_count > move)
|
||||
{
|
||||
memcpy (pout, plit, move);
|
||||
pout += move;
|
||||
plit += move;
|
||||
literal_count -= move;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (pout, plit, literal_count);
|
||||
}
|
||||
|
||||
pout += literal_count;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
pt = &offset_decode.table[offset_state];
|
||||
offset_basebits = pt->basebits;
|
||||
offset_baseline = pt->baseline;
|
||||
@@ -4952,40 +5011,6 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely (seq >= seq_count))
|
||||
{
|
||||
/* Copy remaining literals. */
|
||||
if (literal_count > 0 && plit != pout)
|
||||
{
|
||||
if (unlikely ((size_t)(poutend - pout)
|
||||
< literal_count))
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t)(plit - pout) < literal_count)
|
||||
{
|
||||
uint32_t move;
|
||||
|
||||
move = plit - pout;
|
||||
while (literal_count > move)
|
||||
{
|
||||
memcpy (pout, plit, move);
|
||||
pout += move;
|
||||
plit += move;
|
||||
literal_count -= move;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (pout, plit, literal_count);
|
||||
}
|
||||
|
||||
pout += literal_count;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pin = pblockend;
|
||||
@@ -5014,7 +5039,42 @@ elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
pin += 4;
|
||||
}
|
||||
|
||||
if (pin != pinend)
|
||||
*ppin = pin;
|
||||
*ppout = pout;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decompress a zstd stream from PIN/SIN to POUT/SOUT. Code based on RFC 8878.
|
||||
Return 1 on success, 0 on error. */
|
||||
|
||||
static int
|
||||
elf_zstd_decompress (const unsigned char *pin, size_t sin,
|
||||
unsigned char *zdebug_table, unsigned char *pout,
|
||||
size_t sout)
|
||||
{
|
||||
const unsigned char *pinend;
|
||||
|
||||
pinend = pin + sin;
|
||||
|
||||
while (sin > 0)
|
||||
{
|
||||
const unsigned char *pin_frame;
|
||||
unsigned char *pout_frame;
|
||||
|
||||
pin_frame = pin;
|
||||
pout_frame = pout;
|
||||
if (!elf_zstd_decompress_frame (&pin_frame, pinend, zdebug_table,
|
||||
&pout_frame, sout))
|
||||
return 0;
|
||||
|
||||
sin -= pin_frame - pin;
|
||||
pin = pin_frame;
|
||||
sout -= pout_frame - pout;
|
||||
pout = pout_frame;
|
||||
}
|
||||
|
||||
if (sout > 0)
|
||||
{
|
||||
elf_uncompress_failed ();
|
||||
return 0;
|
||||
@@ -7410,9 +7470,17 @@ phdr_callback_mock (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
|
||||
ptr->dlpi_addr = info->dlpi_addr;
|
||||
|
||||
// calculate the end address as well, so we can quickly determine if a PC is within the range of this image
|
||||
ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr) + (info->dlpi_phnum ? uintptr_t(
|
||||
info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr +
|
||||
info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz) : 0);
|
||||
// headers aren't guaranteed to be in address order; find the max
|
||||
ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr);
|
||||
for (uint32_t i = 0; i < info->dlpi_phnum; i++)
|
||||
{
|
||||
const auto &phdr = info->dlpi_phdr[i];
|
||||
if (phdr.p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
const auto phdr_end = uintptr_t(info->dlpi_addr + phdr.p_vaddr + phdr.p_memsz);
|
||||
ptr->dlpi_end_addr = std::max(phdr_end, ptr->dlpi_end_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user