Commit e44066b3 authored by Petteri Mäki's avatar Petteri Mäki
Browse files

shuffle-ld functionality

parent 6e256507
...@@ -666,7 +666,7 @@ Lex::one_char_operator(char c1) ...@@ -666,7 +666,7 @@ Lex::one_char_operator(char c1)
} }
// Skip a C style comment. *PP points to just after the "/*". Return // Skip a C style comment. *PP points to just after the "/*". Return
// false if the comment did not end. // false if the comment did not end. */
bool bool
Lex::skip_c_comment(const char** pp) Lex::skip_c_comment(const char** pp)
......
...@@ -88,6 +88,7 @@ typedef enum ...@@ -88,6 +88,7 @@ typedef enum
{ {
none, by_name, by_alignment, by_name_alignment, by_alignment_name, none, by_name, by_alignment, by_name_alignment, by_alignment_name,
by_none, by_init_priority by_none, by_init_priority
,SHUFFLE_OBFUSCATION
} sort_type; } sort_type;
extern sort_type sort_section; extern sort_type sort_section;
......
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#include "plugin.h" #include "plugin.h"
#endif /* ENABLE_PLUGINS */ #endif /* ENABLE_PLUGINS */
#include "md5.h"
#ifndef offsetof #ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER)) #define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
#endif #endif
...@@ -411,6 +413,71 @@ get_init_priority (const char *name) ...@@ -411,6 +413,71 @@ get_init_priority (const char *name)
return 0; return 0;
} }
typedef struct
{
uint32_t data[128/(8*sizeof(uint32_t))];
} md5_digest;
static struct md5_memory_entry
{
md5_digest digest;
char * str; // owned
struct md5_memory_entry * next;
} * md5_memory = NULL;
static bfd_boolean md5_collisions = FALSE;
static void
check_md5_memory (const char * str, const md5_digest * digest)
{
struct md5_memory_entry ** next_ptr = &md5_memory;
for (struct md5_memory_entry * entry = md5_memory; entry != NULL; entry = entry->next)
{
next_ptr = &entry->next;
if (memcmp ((const void *) digest, (const void *) &entry->digest, 128/8) == 0)
{
if (strcmp (str, entry->str) == 0)
return;
else if (!md5_collisions)
{
einfo (_("There are md5 collisions in shuffle obfuscation.\n"));
md5_collisions = TRUE;
}
}
}
/* The hash was not found in the memory. */
ASSERT (*next_ptr = (struct md5_memory_entry *) malloc(sizeof(struct md5_memory_entry)));
(*next_ptr)->digest = *digest;
ASSERT ((*next_ptr)->str = (char *) malloc(strlen(str)+1));
strcpy ((*next_ptr)->str, str);
(*next_ptr)->next = NULL;
}
static md5_digest
digest_section_name (const char * name)
{
const char * salt = getenv ("SHUFFLE_OBFUSCATION_SALT");
struct md5_ctx ctx;
md5_digest result;
if (salt == NULL)
{
static bfd_boolean warning_reported = FALSE;
salt = "";
if (!warning_reported)
{
einfo (_("Forgot to set environment variable SHUFFLE_OBFUSCATION_SALT?\n"));
warning_reported = TRUE;
}
}
md5_init_ctx (&ctx);
md5_process_bytes ((const void *) salt, strlen (salt), &ctx);
md5_process_bytes ((const void *) name, strlen (name), &ctx);
(void) md5_finish_ctx (&ctx, (void *) &result);
return result;
}
/* Compare sections ASEC and BSEC according to SORT. */ /* Compare sections ASEC and BSEC according to SORT. */
static int static int
...@@ -461,11 +528,38 @@ sort_by_name: ...@@ -461,11 +528,38 @@ sort_by_name:
ret = (bfd_section_alignment (bsec->owner, bsec) ret = (bfd_section_alignment (bsec->owner, bsec)
- bfd_section_alignment (asec->owner, asec)); - bfd_section_alignment (asec->owner, asec));
break; break;
case SHUFFLE_OBFUSCATION:
{
md5_digest digest_a, digest_b;
digest_a = digest_section_name (bfd_get_section_name (asec->owner, asec));
digest_b = digest_section_name (bfd_get_section_name (bsec->owner, bsec));
check_md5_memory(bfd_get_section_name (asec->owner, asec), &digest_a);
check_md5_memory(bfd_get_section_name (bsec->owner, bsec), &digest_b);
ret = memcmp ((const void *) &digest_a, (const void*) &digest_b, 128/8);
}
break;
} }
return ret; return ret;
} }
#if 0
/* Shuffle instead of sorting. */
static lang_section_bst_type **
wild_shuffle_fast (lang_wild_statement_type *wild,
struct wildcard_list *sec,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
asection *section)
{
// TODO!
(void) wild;
(void) sec;
(void) section;
return NULL;
}
#endif
/* Build a Binary Search Tree to sort sections, unlike insertion sort /* Build a Binary Search Tree to sort sections, unlike insertion sort
used in wild_sort(). BST is considerably faster if the number of used in wild_sort(). BST is considerably faster if the number of
of sections are large. */ of sections are large. */
...@@ -524,6 +618,7 @@ output_section_callback_fast (lang_wild_statement_type *ptr, ...@@ -524,6 +618,7 @@ output_section_callback_fast (lang_wild_statement_type *ptr,
node->right = 0; node->right = 0;
node->section = section; node->section = section;
/* tree = (sec->spec.sorted == SHUFFLE_OBFUSCATION ? wild_shuffle_fast : wild_sort_fast) (ptr, sec, file, section); */
tree = wild_sort_fast (ptr, sec, file, section); tree = wild_sort_fast (ptr, sec, file, section);
if (tree != NULL) if (tree != NULL)
*tree = node; *tree = node;
...@@ -2461,6 +2556,23 @@ lang_add_section (lang_statement_list_type *ptr, ...@@ -2461,6 +2556,23 @@ lang_add_section (lang_statement_list_type *ptr,
new_section->section = section; new_section->section = section;
} }
#if 0
/* Shuffle instead of sorting. */
static lang_statement_union_type *
wild_shuffle (lang_wild_statement_type *wild,
struct wildcard_list *sec,
lang_input_statement_type *file,
asection *section) {
// TODO!
(void) wild;
(void) sec;
(void) file;
(void) section;
return NULL;
}
#endif
/* Handle wildcard sorting. This returns the lang_input_section which /* Handle wildcard sorting. This returns the lang_input_section which
should follow the one we are going to create for SECTION and FILE, should follow the one we are going to create for SECTION and FILE,
based on the sorting requirements of WILD. It returns NULL if the based on the sorting requirements of WILD. It returns NULL if the
...@@ -2577,6 +2689,7 @@ output_section_callback (lang_wild_statement_type *ptr, ...@@ -2577,6 +2689,7 @@ output_section_callback (lang_wild_statement_type *ptr,
if (unique_section_p (section, os)) if (unique_section_p (section, os))
return; return;
/* before = (sec->spec.sorted == SHUFFLE_OBFUSCATION ? wild_shuffle : wild_sort) (ptr, sec, file, section); */
before = wild_sort (ptr, sec, file, section); before = wild_sort (ptr, sec, file, section);
/* Here BEFORE points to the lang_input_section which /* Here BEFORE points to the lang_input_section which
...@@ -3528,6 +3641,7 @@ update_wild_statements (lang_statement_union_type *s) ...@@ -3528,6 +3641,7 @@ update_wild_statements (lang_statement_union_type *s)
case by_name: case by_name:
case by_alignment: case by_alignment:
case SHUFFLE_OBFUSCATION:
for (; s != NULL; s = s->header.next) for (; s != NULL; s = s->header.next)
{ {
switch (s->header.type) switch (s->header.type)
...@@ -3552,6 +3666,9 @@ update_wild_statements (lang_statement_union_type *s) ...@@ -3552,6 +3666,9 @@ update_wild_statements (lang_statement_union_type *s)
if (sort_section == by_name) if (sort_section == by_name)
sec->spec.sorted = by_alignment_name; sec->spec.sorted = by_alignment_name;
break; break;
case SHUFFLE_OBFUSCATION:
FAIL (); /* TODO! */
break;
default: default:
break; break;
} }
......
...@@ -426,7 +426,7 @@ static const struct ld_option ld_options[] = ...@@ -426,7 +426,7 @@ static const struct ld_option ld_options[] =
{ {"sort_common", no_argument, NULL, OPTION_SORT_COMMON}, { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
'\0', NULL, NULL, NO_HELP }, '\0', NULL, NULL, NO_HELP },
{ {"sort-section", required_argument, NULL, OPTION_SORT_SECTION}, { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
'\0', N_("name|alignment"), '\0', N_("name|alignment|shuffle_obfuscation"),
N_("Sort sections by name or maximum alignment"), TWO_DASHES }, N_("Sort sections by name or maximum alignment"), TWO_DASHES },
{ {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS}, { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
'\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"), '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
...@@ -1192,6 +1192,8 @@ parse_args (unsigned argc, char **argv) ...@@ -1192,6 +1192,8 @@ parse_args (unsigned argc, char **argv)
sort_section = by_name; sort_section = by_name;
else if (strcmp (optarg, N_("alignment")) == 0) else if (strcmp (optarg, N_("alignment")) == 0)
sort_section = by_alignment; sort_section = by_alignment;
else if (strcmp (optarg, N_("shuffle_obfuscation")) == 0)
sort_section = SHUFFLE_OBFUSCATION;
else else
einfo (_("%P%F: invalid section sorting option: %s\n"), einfo (_("%P%F: invalid section sorting option: %s\n"),
optarg); optarg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment