Skip to content
This repository has been archived by the owner on May 2, 2021. It is now read-only.

First shot at gum_stalker_prefetch support #10

Closed
wants to merge 1 commit into from
Closed

Conversation

meme
Copy link
Owner

@meme meme commented Jan 24, 2021

Thanks to @WorksButNotTested for adding this feature to Frida

Closes #2

Thanks to @WorksButNotTested for adding this feature to Frida
Copy link
Contributor

@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.

w00t! 🚀

static void prefetch_log(const GumEvent* event, GumCpuContext* cpu_context, gpointer user_data) {
switch (event->type) {
case GUM_COMPILE: {
const GumCompileEvent* compile = &event->compile;

Choose a reason for hiding this comment

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

You could consider doing this in the transformer to avoid the need for a separate event sink. This may help performance.

gpointer key, value;
g_hash_table_iter_init(&iter, table);
while (g_hash_table_iter_next(&iter, &key, &value)) {
int status = write(fd, &key, sizeof(key));

Choose a reason for hiding this comment

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

I would consider using a shared memory IPC like AFL already uses for the coverage bitmap. This way, you should not need any syscalls and hence any world switches after the initial setup.


static void prefetch_read(int fd, GHashTable *table) {
gpointer block_address;
while (read(fd, &block_address, sizeof(block_address)) == sizeof(block_address)) {

Choose a reason for hiding this comment

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

If you prefer the pipes, you could consider reading a buffer full of address in one go to reduce the number of syscalls. This could be further reduced if prefetching is only triggered every 'n' forks. Whilst slower during the initial run-up, this will be quicker later on when there are few new paths being discovered.


// This is written into by "prefetch_log".
//
prefetch_compiled = g_hash_table_new(NULL, NULL);

Choose a reason for hiding this comment

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

I went with a single hash table as follows:

  • The parent creates a hash table of prefetched blocks during init.
  • The child inherits a COPY of this on fork.
  • The child checks the hash table before writing a block to the IPC
  • The child then adds the block to its copy of the hash table to avoid any duplicates being sent.
  • The parent reads blocks from the IPC and updates its copy of the hash table as it goes.
  • The hash table is then inherited by the next child.

@@ -58,6 +127,8 @@ int main(int argc, char* argv[]) {

gum_stalker_unfollow_me(stalker);

prefetch_write(compile_pipes[STDOUT_FILENO], prefetch_compiled);

Choose a reason for hiding this comment

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

You could consider omitting the garbage collection step as you are about to bin the child anyway. You might get some performance gain.

@@ -1,6 +1,6 @@
/*
Copyright 2013 Google LLC All rights reserved.
Copyright 2020 Keegan S. <keegan@sdf.org>
Copyright 2020 Keegan Saunders <keegan@undefinedbehaviour.org>

Choose a reason for hiding this comment

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

Looks good to me. Does it help performance any? I've had a few thoughts below on how you might squeeze a little bit more performance out of it.

@meme meme mentioned this pull request Feb 8, 2021
@meme
Copy link
Owner Author

meme commented Mar 5, 2021

Closing in favour of #15

@meme meme closed this Mar 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reduce instrumentation overhead
3 participants