Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align all memory used by the system symbol table #297

Merged
merged 1 commit into from
Jun 22, 2022

Conversation

sadderchris
Copy link
Contributor

Issue #, if available: N/A

Description of changes:

Rarely, the compiler/linker will decide to put gSystemSymbolMemory on a smaller alignment boundary (e.g. 4 bytes) than what is required for the data it contains. gSystemSymbolMemory is declared as a char[], but is really being used as generic backing memory for the system symbol table and any other data structures associated with it. Notably, the very first data structure placed in the gSystemSymbolMemory is an ION_ALLOCATION_CHAIN, which may need a wider alignment.

With the current behavior, an ION_ALLOCATION_CHAIN could be allocated at a smaller alignment than needed. The ION_ALLOC_BLOCK_TO_USER_PTR macro then gets an aligned offset into the memory chunk associated with the ION_ALLOCATION_CHAIN. When another allocation needs to be performed, the ION_ALLOC_USER_PTR_TO_BLOCK macro is used to convert the user data pointer into an ION_ALLOCATION_CHAIN, but this is where the problems start happening. Because ION_ALLOC_BLOCK_TO_USER_PTR aligns the user data pointer, an unknown amount of padding exists between the end of the ION_ALLOCATION_CHAIN and the user data pointer (up to ALLOC_ALIGNMENT bytes). ION_ALLOC_USER_PTR_TO_BLOCK doesn't account for any alignment done to the user data pointer (and there's no way it can really), meaning it might produce a pointer that is offset from the actual ION_ALLOCATION_CHAIN by the amount of padding that exists. This usually leads to a crash, since the data being read is now scrambled.

This commit addresses this issue by introducing an ALIGN_AS macro that forces a data structure to be aligned to a wider alignment than the type requires. This is applied to the gSystemSymbolMemory array, so that it is always located at a correctly aligned address. This also adds a few debug assertions to the system symbol table allocation routines and gets rid of the pointer aligning behavior in the ION_ALLOC converter macros (an offset from a pointer should be aligned if you start with an aligned pointer and add an aligned offset to it; in the case that you start with a misaligned pointer, you'll at least get the right pointer back with a round trip conversion, rather than a misaligned one).

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Rarely, the compiler/linker will decide to put `gSystemSymbolMemory` on
a smaller alignment boundary (e.g. 4 bytes) than what is required for
the data it contains.  `gSystemSymbolMemory` is declared as a `char[]`,
but is really being used as generic backing memory for the system symbol
table and any other data structures associated with it.  Notably, the
very first data structure placed in the `gSystemSymbolMemory` is an
`ION_ALLOCATION_CHAIN`, which may need a wider alignment.

With the current behavior, an `ION_ALLOCATION_CHAIN` could be allocated
at a smaller alignment than needed.  The `ION_ALLOC_BLOCK_TO_USER_PTR`
macro then gets an aligned offset into the memory chunk associated with the
`ION_ALLOCATION_CHAIN`.  When another allocation needs to be performed,
the `ION_ALLOC_USER_PTR_TO_BLOCK` macro is used to convert the user data
pointer into an `ION_ALLOCATION_CHAIN`, but this is where the problems
start happening.  Because `ION_ALLOC_BLOCK_TO_USER_PTR` aligns the user data pointer,
an unknown amount of padding exists between the end of the
`ION_ALLOCATION_CHAIN` and the user data pointer (up to `ALLOC_ALIGNMENT` bytes).
`ION_ALLOC_USER_PTR_TO_BLOCK` doesn't account for any
alignment done to the user data pointer (and there's no way it can
really), meaning it might produce a pointer that is offset from the
actual `ION_ALLOCATION_CHAIN` by the amount of padding that exists.
This usually leads to a crash, since the data being read is now
scrambled.

This commit addresses this issue by introducing an `ALIGN_AS` macro that forces
a data structure to be aligned to a wider alignment than the type
requires.  This is applied to the `gSystemSymbolMemory` array, so that
it is always located at a correctly aligned address.  This also adds a
few debug assertions to the system symbol table allocation routines
and gets rid of the pointer aligning behavior in the `ION_ALLOC`
converter macros (an offset from a pointer should be aligned if you start with an
aligned pointer and add an aligned offset to it; in the case that you
start with a misaligned pointer, you'll at least get the right pointer
back with a round trip conversion, rather than a misaligned one).
@sadderchris sadderchris marked this pull request as ready for review June 21, 2022 19:29
@tgregg tgregg merged commit bdb8fee into amazon-ion:master Jun 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants