libsframe asan: avoid generating misaligned loads

There are two places where unaligned loads were seen on aarch64:
  - #1. access to the SFrame FRE stack offsets in the in-memory
    representation/abstraction provided by libsframe.
  - #2. access to the SFrame FRE start address in the on-disk representation
    of the frame row entry.

For #1, we can fix this by reordering the struct members of
sframe_frame_row_entry in libsframe/sframe-api.h.

For #2, we need to default to using memcpy instead, and copy out the bytes
to a location for output.

SFrame format is an unaligned on-disk format. As such, there are other blobs
of memory in the on-disk SFrame FRE that are on not on their natural
boundaries.  But that does not pose further problems yet, because the users
are provided access to the on-disk SFrame FRE data via libsframe's
sframe_frame_row_entry, the latter has its' struct members aligned on their
respective natural boundaries (and initialized using memcpy).

PR 29856 libsframe asan: load misaligned at sframe.c:516

ChangeLog:

	PR libsframe/29856
	* bfd/elf64-x86-64.c: Adjust as the struct members have been
	reordered.
	* libsframe/sframe.c (sframe_decode_fre_start_address): Use
	memcpy to perform 16-bit/32-bit reads.
	* libsframe/testsuite/libsframe.encode/encode-1.c: Adjust as the
	struct members have been reordered.

include/ChangeLog:

	PR libsframe/29856
	* sframe-api.h: Reorder fre_offsets for natural alignment.
This commit is contained in:
Indu Bhagat
2022-12-15 13:12:01 -08:00
parent 69de431392
commit 8c078abdc2
4 changed files with 42 additions and 24 deletions

View File

@@ -652,6 +652,11 @@ sframe_frame_row_entry_copy (sframe_frame_row_entry *dst, sframe_frame_row_entry
return 0;
}
/* Decode the SFrame FRE start address offset value from FRE_BUF in on-disk
binary format, given the FRE_TYPE. Updates the FRE_START_ADDR.
Returns 0 on success, SFRAME_ERR otherwise. */
static int
sframe_decode_fre_start_address (const char *fre_buf,
uint32_t *fre_start_addr,
@@ -659,6 +664,9 @@ sframe_decode_fre_start_address (const char *fre_buf,
{
uint32_t saddr = 0;
int err = 0;
size_t addr_size = 0;
addr_size = sframe_fre_start_addr_size (fre_type);
if (fre_type == SFRAME_FRE_TYPE_ADDR1)
{
@@ -668,12 +676,18 @@ sframe_decode_fre_start_address (const char *fre_buf,
else if (fre_type == SFRAME_FRE_TYPE_ADDR2)
{
uint16_t *ust = (uint16_t *)fre_buf;
saddr = (uint32_t)*ust;
/* SFrame is an unaligned on-disk format. Using memcpy helps avoid the
use of undesirable unaligned loads. See PR libsframe/29856. */
uint16_t tmp = 0;
memcpy (&tmp, ust, addr_size);
saddr = (uint32_t)tmp;
}
else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
{
uint32_t *uit = (uint32_t *)fre_buf;
saddr = (uint32_t)*uit;
int32_t tmp = 0;
memcpy (&tmp, uit, addr_size);
saddr = (uint32_t)tmp;
}
else
return sframe_set_errno (&err, SFRAME_ERR_INVAL);