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

Darwin: Fixup TLV thunk functions during mapping #709

Closed

Conversation

fabianfreyer
Copy link
Contributor

See-also: frida/frida#2395

@fabianfreyer fabianfreyer force-pushed the feat/darwin-mapper-fix-tlv branch 4 times, most recently from b206895 to 3100050 Compare January 31, 2023 11:57
@fabianfreyer fabianfreyer force-pushed the feat/darwin-mapper-fix-tlv branch 10 times, most recently from 50ff3b0 to ec981e5 Compare February 9, 2023 00:11
@fabianfreyer
Copy link
Contributor Author

fabianfreyer commented Feb 9, 2023

Tested on M1 / amd64 macOS. The memory budget for the additional code is a bit generous (196 bytes over the 134 bytes for x86 and the 92 bytes for arm64). I'm not sure whether anything would still need to be done to account for PAC/arm64e, but I'm also very unsure how to test that.

Copy link
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 🙌

This will need some style fixes. The style is documented here.

(Happy to help with tweaking the style once I have a bit more bandwidth, but leaving this note here in the meantime.)

@fabianfreyer
Copy link
Contributor Author

I tried to fix the style issues -- in case I overlooked some rule, please let me know :)

@fabianfreyer fabianfreyer force-pushed the feat/darwin-mapper-fix-tlv branch 2 times, most recently from dbf12e8 to 4ac5b53 Compare August 15, 2023 23:55
@fabianfreyer fabianfreyer force-pushed the feat/darwin-mapper-fix-tlv branch 3 times, most recently from 67b1c59 to d12a99e Compare September 2, 2023 12:05
@fabianfreyer
Copy link
Contributor Author

Rebased, added runtime code to copy over the initial values for the Frida thread, and added somewhat-verbose commit messages describing what's happening.

@fabianfreyer fabianfreyer force-pushed the feat/darwin-mapper-fix-tlv branch 2 times, most recently from 03de284 to 252699f Compare September 2, 2023 12:16
Within a Mach-O image, each TLV descriptor contains a thunk function
pointer to resolve the variable's address, a thread key, and an offset
to be used to index into the per-thread area. At runtime the thunk
function is invoked, passed a pointer to the TLV descriptor, and returns
a pointer to the TLV storage.

Add functions to parse these from an Image.
Dyld has a randezvous area in a section named `__DATA,__dyld4`, where it
exposes its public API. This includes a pointer to tlv_get_addr at a
well-known offset within this section.
These hold the initial values for TLV.
Within a module's image, before loading, the TLV descriptors thunk
function is set to _tlv_bootstrap, which calls abort at runtime.
The key values are also set to 0 on non-dyld_shared_cache images.

We create a new pthread_key at runtime, and store it in each TLV
descriptor. Additionally, we fix up the thunk function to tlv_get_addr,
which returns a pointer to the variable's storage as
((void**) gsbase)[descriptor->key] + descriptor->offset.

We're not handling any non-zero keys in the image, as those are only
used within the dyld_shared_cache.
Dyld's tlv_get_addr function retrieves the thread local storage by
using a descriptor's key to index into the thread local storage held in
gsbase on x86 or TPIDRRO_EL0 on arm64 to retrieve a thread- and module-
specific data area to offset into.

If this offset-specific area pointer is NULL, it will be lazily
allocated by tlv_get_addr through a call to
RuntimeState::_instantiateTLVs. This allocates the area, using a size
stored in a Dyld-private vector _tlvInfos, and copies over intial data.
When a module is loaded through Dyld, it stores the nesseary size along
with the key in _tlvInfos.

Since we don't have a way to insert our newly generated key into
this array through public (and hence stable) APIs, we pre-allocate and
initialize the per-thread area for the initial thread in the runtime.
@oleavr
Copy link
Member

oleavr commented Oct 6, 2023

Landed in 5f81484. Thanks! 🙌

@oleavr oleavr closed this Oct 6, 2023
@fabianfreyer
Copy link
Contributor Author

Wonderful, thank you so much!

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