summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-03 11:22:26 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-03 11:22:26 +0200
commitead2f1961fc653861a151a033c3cd0657c50af16 (patch)
treecc28f63f2fd690bd9287c7793cda1b604560e912
parent4b0939539fb99ee8a399d8a59d295ff94c1eeebc (diff)
downloadintel-quark-d2000-playground-ead2f1961fc653861a151a033c3cd0657c50af16.tar.gz
intel-quark-d2000-playground-ead2f1961fc653861a151a033c3cd0657c50af16.tar.bz2
intel-quark-d2000-playground-ead2f1961fc653861a151a033c3cd0657c50af16.tar.xz
intel-quark-d2000-playground-ead2f1961fc653861a151a033c3cd0657c50af16.zip
LD file Antlr4 grammar. Generates a lexer and parser for Java.
-rw-r--r--cmake/elfinfo/.gitignore4
-rw-r--r--cmake/elfinfo/GnuLd.g41500
-rw-r--r--cmake/elfinfo/Makefile.grammar53
-rwxr-xr-xcmake/elfinfo/grun.sh14
-rw-r--r--cmake/elfinfo/lds/d2000.ld85
-rw-r--r--cmake/elfinfo/lds/stm32.ld62
-rw-r--r--cmake/elfinfo/pom.xml34
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java483
8 files changed, 2235 insertions, 0 deletions
diff --git a/cmake/elfinfo/.gitignore b/cmake/elfinfo/.gitignore
index 485dee6..a2d5086 100644
--- a/cmake/elfinfo/.gitignore
+++ b/cmake/elfinfo/.gitignore
@@ -1 +1,5 @@
.idea
+*.iml
+*.iws
+*.jar
+/antlr
diff --git a/cmake/elfinfo/GnuLd.g4 b/cmake/elfinfo/GnuLd.g4
new file mode 100644
index 0000000..da7b01f
--- /dev/null
+++ b/cmake/elfinfo/GnuLd.g4
@@ -0,0 +1,1500 @@
+grammar GnuLd;
+
+/*
+TODO: check right associative annotations
+*/
+
+/*
+%token <bigint> INT
+%token <name> NAME LNAME
+*/
+
+/*
+%right UNARY
+%token END
+%left <token> '('
+*/
+
+
+file:
+ /*INPUT_SCRIPT*/ script_file
+ | /*INPUT_MRI_SCRIPT*/ mri_script_file
+ | /*INPUT_VERSION_SCRIPT*/ version_script_file
+ | /*INPUT_DYNAMIC_LIST*/ dynamic_list_file
+ | /*INPUT_DEFSYM*/ defsym_expr
+ ;
+
+filename: NAME;
+
+
+defsym_expr:
+// { ldlex_defsym(); }
+ NAME '=' exp
+// {
+// ldlex_popstate();
+// lang_add_assignment (exp_defsym ($2, $4));
+// }
+ ;
+
+/* SYNTAX WITHIN AN MRI SCRIPT FILE */
+mri_script_file:
+// {
+// ldlex_mri_script ();
+// PUSH_ERROR (_("MRI style script"));
+// }
+ mri_script_lines
+// {
+// ldlex_popstate ();
+// mri_draw_tree ();
+// POP_ERROR ();
+// }
+ ;
+
+mri_script_lines:
+ mri_script_lines mri_script_command NEWLINE
+ |
+ ;
+
+mri_script_command:
+ CHIP exp
+ | CHIP exp ',' exp
+ | NAME /*{
+ einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1);
+ }*/
+ | LIST /*{
+ config.map_filename = "-";
+ }*/
+ | ORDER ordernamelist
+ | ENDWORD
+ | PUBLIC NAME '=' exp
+ // { mri_public($2, $4); }
+ | PUBLIC NAME ',' exp
+ // { mri_public($2, $4); }
+ | PUBLIC NAME exp
+ // { mri_public($2, $3); }
+ | FORMAT NAME
+ // { mri_format($2); }
+ | SECT NAME ',' exp
+ // { mri_output_section($2, $4);}
+ | SECT NAME exp
+ // { mri_output_section($2, $3);}
+ | SECT NAME '=' exp
+ // { mri_output_section($2, $4);}
+ | ALIGN_K NAME '=' exp
+ // { mri_align($2,$4); }
+ | ALIGN_K NAME ',' exp
+ // { mri_align($2,$4); }
+ | ALIGNMOD NAME '=' exp
+ // { mri_alignmod($2,$4); }
+ | ALIGNMOD NAME ',' exp
+ // { mri_alignmod($2,$4); }
+ | ABSOLUTE mri_abs_name_list
+ | LOAD mri_load_name_list
+ | NAMEWORD NAME
+ // { mri_name($2); }
+ | ALIAS NAME ',' NAME
+ // { mri_alias($2,$4,0);}
+ | ALIAS NAME ',' INT
+ // { mri_alias ($2, 0, (int) $4.integer); }
+ | BASE exp
+ // { mri_base($2); }
+ | TRUNCATE INT
+ // { mri_truncate ((unsigned int) $2.integer); }
+ | CASE casesymlist
+ | EXTERN extern_name_list
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ mri_script_lines END
+ // { ldlex_popstate (); }
+ | START NAME
+ // { lang_add_entry ($2, FALSE); }
+ |
+ ;
+
+ordernamelist:
+ ordernamelist ',' NAME // { mri_order($3); }
+ | ordernamelist NAME // { mri_order($2); }
+ |
+ ;
+
+mri_load_name_list:
+ NAME
+ // { mri_load($1); }
+ | mri_load_name_list ',' NAME // { mri_load($3); }
+ ;
+
+mri_abs_name_list:
+ NAME
+ // { mri_only_load($1); }
+ | mri_abs_name_list ',' NAME
+ // { mri_only_load($3); }
+ ;
+
+casesymlist:
+ /* empty */ // { $$ = NULL; }
+ | NAME
+ | casesymlist ',' NAME
+ ;
+
+/* Parsed as expressions so that commas separate entries */
+extern_name_list:
+ // { ldlex_expression (); }
+ extern_name_list_body
+ // { ldlex_popstate (); }
+ ;
+
+extern_name_list_body:
+ NAME
+ // { ldlang_add_undef ($1, FALSE); }
+ | extern_name_list_body NAME
+ // { ldlang_add_undef ($2, FALSE); }
+ | extern_name_list_body ',' NAME
+ // { ldlang_add_undef ($3, FALSE); }
+ ;
+
+script_file:
+ // { ldlex_both(); }
+ ifile_list
+ // { ldlex_popstate(); }
+ ;
+
+ifile_list:
+ ifile_list ifile_p1
+ |
+ ;
+
+
+ifile_p1:
+ memory
+ | sections
+ | phdrs
+ | startup
+ | high_level_library
+ | low_level_library
+ | floating_point_support
+ | statement_anywhere
+ | version
+ | ';'
+ | TARGET_K '(' NAME ')'
+ // { lang_add_target($3); }
+ | SEARCH_DIR '(' filename ')'
+ // { ldfile_add_library_path ($3, FALSE); }
+ | OUTPUT '(' filename ')'
+ // { lang_add_output($3, 1); }
+ | OUTPUT_FORMAT '(' NAME ')'
+ // { lang_add_output_format ($3, (char *) NULL,
+ // (char *) NULL, 1); }
+ | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
+ // { lang_add_output_format ($3, $5, $7, 1); }
+ | OUTPUT_ARCH '(' NAME ')'
+ // { ldfile_set_output_arch ($3, bfd_arch_unknown); }
+ | FORCE_COMMON_ALLOCATION
+ // { command_line.force_common_definition = TRUE ; }
+ | INHIBIT_COMMON_ALLOCATION
+ // { command_line.inhibit_common_definition = TRUE ; }
+ | INPUT '(' input_list ')'
+ | GROUP
+ // { lang_enter_group (); }
+ '(' input_list ')'
+ // { lang_leave_group (); }
+ | MAP '(' filename ')'
+ // { lang_add_map($3); }
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ ifile_list END
+ // { ldlex_popstate (); }
+ | NOCROSSREFS '(' nocrossref_list ')'
+ // {
+ // lang_add_nocrossref ($3);
+ // }
+ | NOCROSSREFS_TO '(' nocrossref_list ')'
+ // {
+ // lang_add_nocrossref_to ($3);
+ // }
+ | EXTERN '(' extern_name_list ')'
+ | INSERT_K AFTER NAME
+ // { lang_add_insert ($3, 0); }
+ | INSERT_K BEFORE NAME
+ // { lang_add_insert ($3, 1); }
+ | REGION_ALIAS '(' NAME ',' NAME ')'
+ // { lang_memory_region_alias ($3, $5); }
+ | LD_FEATURE '(' NAME ')'
+ // { lang_ld_feature ($3); }
+ ;
+
+input_list:
+ // { ldlex_inputlist(); }
+ input_list1
+ // { ldlex_popstate(); }
+ ;
+
+input_list1:
+ NAME
+ // { lang_add_input_file($1,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | input_list1 ',' NAME
+ // { lang_add_input_file($3,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | input_list1 NAME
+ // { lang_add_input_file($2,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | LNAME
+ // { lang_add_input_file($1,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | input_list1 ',' LNAME
+ // { lang_add_input_file($3,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | input_list1 LNAME
+ // { lang_add_input_file($2,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>3; }
+ | input_list1 ',' AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>5; }
+ | input_list1 AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>4; }
+ ;
+
+sections:
+ SECTIONS '{' sec_or_group_p1 '}'
+ ;
+
+sec_or_group_p1:
+ sec_or_group_p1 section
+ | sec_or_group_p1 statement_anywhere
+ |
+ ;
+
+statement_anywhere:
+ ENTRY '(' NAME ')'
+ // { lang_add_entry ($3, FALSE); }
+ | assignment end
+ | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')'
+ // { ldlex_popstate ();
+ // lang_add_assignment (exp_assert ($4, $6)); }
+ ;
+
+/* The '*' and '?' cases are there because the lexer returns them as
+ separate tokens rather than as NAME. */
+wildcard_name:
+ NAME
+ // {
+ // $$ = $1;
+ // }
+ | '*'
+ // {
+ // $$ = "*";
+ // }
+ | '?'
+ // {
+ // $$ = "?";
+ // }
+ ;
+
+wildcard_spec:
+ wildcard_name
+// {
+// $$.name = $1;
+// $$.sorted = none;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
+// {
+// $$.name = $5;
+// $$.sorted = none;
+// $$.exclude_name_list = $3;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_NONE '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_none;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_name_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_alignment_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
+// {
+// $$.name = $7;
+// $$.sorted = by_name;
+// $$.exclude_name_list = $5;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_INIT_PRIORITY '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_init_priority;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ ;
+
+sect_flag_list: NAME
+// {
+// struct flag_info_list *n;
+// n = ((struct flag_info_list *) xmalloc (sizeof *n));
+// if ($1[0] == '!')
+// {
+// n->with = without_flags;
+// n->name = &$1[1];
+// }
+// else
+// {
+// n->with = with_flags;
+// n->name = $1;
+// }
+// n->valid = FALSE;
+// n->next = NULL;
+// $$ = n;
+// }
+ | sect_flag_list '&' NAME
+// {
+// struct flag_info_list *n;
+// n = ((struct flag_info_list *) xmalloc (sizeof *n));
+// if ($3[0] == '!')
+// {
+// n->with = without_flags;
+// n->name = &$3[1];
+// }
+// else
+// {
+// n->with = with_flags;
+// n->name = $3;
+// }
+// n->valid = FALSE;
+// n->next = $1;
+// $$ = n;
+// }
+ ;
+
+sect_flags:
+ /*not used by antlr: INPUT_SECTION_FLAGS*/ '(' sect_flag_list ')'
+// {
+// struct flag_info *n;
+// n = ((struct flag_info *) xmalloc (sizeof *n));
+// n->flag_list = $3;
+// n->flags_initialized = FALSE;
+// n->not_with_flags = 0;
+// n->only_with_flags = 0;
+// $$ = n;
+// }
+ ;
+
+exclude_name_list:
+ exclude_name_list wildcard_name
+// {
+// struct name_list *tmp;
+// tmp = (struct name_list *) xmalloc (sizeof *tmp);
+// tmp->name = $2;
+// tmp->next = $1;
+// $$ = tmp;
+// }
+ |
+ wildcard_name
+// {
+// struct name_list *tmp;
+// tmp = (struct name_list *) xmalloc (sizeof *tmp);
+// tmp->name = $1;
+// tmp->next = NULL;
+// $$ = tmp;
+// }
+ ;
+
+file_NAME_list:
+ file_NAME_list opt_comma wildcard_spec
+// {
+// struct wildcard_list *tmp;
+// tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
+// tmp->next = $1;
+// tmp->spec = $3;
+// $$ = tmp;
+// }
+ |
+ wildcard_spec
+// {
+// struct wildcard_list *tmp;
+// tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
+// tmp->next = NULL;
+// tmp->spec = $1;
+// $$ = tmp;
+// }
+ ;
+
+input_section_spec_no_keep:
+ NAME
+// {
+// struct wildcard_spec tmp;
+// tmp.name = $1;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = NULL;
+// lang_add_wild (&tmp, NULL, ldgram_had_keep);
+// }
+ | sect_flags NAME
+// {
+// struct wildcard_spec tmp;
+// tmp.name = $2;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = $1;
+// lang_add_wild (&tmp, NULL, ldgram_had_keep);
+// }
+ | '[' file_NAME_list ']'
+// {
+// lang_add_wild (NULL, $2, ldgram_had_keep);
+// }
+ | sect_flags '[' file_NAME_list ']'
+// {
+// struct wildcard_spec tmp;
+// tmp.name = NULL;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = $1;
+// lang_add_wild (&tmp, $3, ldgram_had_keep);
+// }
+ | wildcard_spec '(' file_NAME_list ')'
+// {
+// lang_add_wild (&$1, $3, ldgram_had_keep);
+// }
+ | sect_flags wildcard_spec '(' file_NAME_list ')'
+// {
+// $2.section_flag_list = $1;
+// lang_add_wild (&$2, $4, ldgram_had_keep);
+// }
+ ;
+
+input_section_spec:
+ input_section_spec_no_keep
+ | KEEP '('
+// { ldgram_had_keep = TRUE; }
+ input_section_spec_no_keep ')'
+// { ldgram_had_keep = FALSE; }
+ ;
+
+statement:
+ assignment end
+ | CREATE_OBJECT_SYMBOLS
+// {
+// lang_add_attribute(lang_object_symbols_statement_enum);
+// }
+ | ';'
+ | CONSTRUCTORS
+// {
+//
+// lang_add_attribute(lang_constructors_statement_enum);
+// }
+ | SORT_BY_NAME '(' CONSTRUCTORS ')'
+// {
+// constructors_sorted = TRUE;
+// lang_add_attribute (lang_constructors_statement_enum);
+// }
+ | input_section_spec
+ | length '(' mustbe_exp ')'
+// {
+// lang_add_data ((int) $1, $3);
+// }
+
+ | FILL '(' fill_exp ')'
+// {
+// lang_add_fill ($3);
+// }
+ | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')' end
+// { ldlex_popstate ();
+// lang_add_assignment (exp_assert ($4, $6)); }
+ | INCLUDE filename
+// { ldlex_script (); ldfile_open_command_file($2); }
+ statement_list_opt END
+// { ldlex_popstate (); }
+ ;
+
+statement_list:
+ statement_list statement
+ | statement
+ ;
+
+statement_list_opt:
+ /* empty */
+ | statement_list
+ ;
+
+length:
+ QUAD
+// { $$ = $1; }
+ | SQUAD
+// { $$ = $1; }
+ | LONG
+// { $$ = $1; }
+ | SHORT
+// { $$ = $1; }
+ | BYTE
+// { $$ = $1; }
+ ;
+
+fill_exp:
+ mustbe_exp
+// {
+// $$ = exp_get_fill ($1, 0, "fill value");
+// }
+ ;
+
+fill_opt:
+ '=' fill_exp
+ // { $$ = $2; }
+ | // { $$ = (fill_type *) 0; }
+ ;
+
+assign_op:
+ PLUSEQ
+// { $$ = '+'; }
+ | MINUSEQ
+// { $$ = '-'; }
+ | MULTEQ
+// { $$ = '*'; }
+ | DIVEQ
+// { $$ = '/'; }
+ | LSHIFTEQ
+// { $$ = LSHIFT; }
+ | RSHIFTEQ
+// { $$ = RSHIFT; }
+ | ANDEQ
+// { $$ = '&'; }
+ | OREQ
+// { $$ = '|'; }
+
+ ;
+
+end: ';' | ','
+ ;
+
+
+assignment:
+ NAME '=' mustbe_exp
+// {
+// lang_add_assignment (exp_assign ($1, $3, FALSE));
+// }
+ | NAME assign_op mustbe_exp
+// {
+// lang_add_assignment (exp_assign ($1,
+// exp_binop ($2,
+// exp_nameop (NAME,
+// $1),
+// $3), FALSE));
+// }
+ | HIDDEN_ '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_assign ($3, $5, TRUE));
+// }
+ | PROVIDE '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_provide ($3, $5, FALSE));
+// }
+ | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_provide ($3, $5, TRUE));
+// }
+ ;
+
+
+opt_comma:
+ ',' | ;
+
+
+memory:
+ MEMORY '{' memory_spec_list_opt '}'
+ ;
+
+memory_spec_list_opt: memory_spec_list | ;
+
+memory_spec_list:
+ memory_spec_list opt_comma memory_spec
+ | memory_spec
+ ;
+
+
+memory_spec: NAME
+// { region = lang_memory_region_lookup ($1, TRUE); }
+ attributes_opt ':'
+ origin_spec opt_comma length_spec
+// {}
+ | INCLUDE filename
+// { ldlex_script (); ldfile_open_command_file($2); }
+ memory_spec_list_opt END
+// { ldlex_popstate (); }
+ ;
+
+origin_spec:
+ ORIGIN '=' mustbe_exp
+// {
+// region->origin_exp = $3;
+// region->current = region->origin;
+// }
+ ;
+
+length_spec:
+ LENGTH '=' mustbe_exp
+// {
+// region->length_exp = $3;
+// }
+ ;
+
+attributes_opt:
+ /* empty */
+ /* { *//* dummy action to avoid bison 1.25 error message *//* }
+ |*/ '(' attributes_list ')'
+ ;
+
+attributes_list:
+ attributes_string
+ | attributes_list attributes_string
+ ;
+
+attributes_string:
+ NAME # attributeNormal
+// { lang_set_flags (region, $1, 0); }
+ | '!' NAME # attributeInverted
+// { lang_set_flags (region, $2, 1); }
+ ;
+
+/*
+This would be best but the tokenizer would have to be made context sensitive which is too much work given how
+easy it is to check the flags after parsing.
+
+attributes_string :
+ attribute
+ | '!' attribute # attributeInverted
+ ;
+
+attribute: 'r' | 'w' | 'x' | 'a' | 'i' | 'l' ;
+*/
+startup:
+ STARTUP '(' filename ')'
+// { lang_startup($3); }
+ ;
+
+high_level_library:
+ HLL '(' high_level_library_NAME_list ')'
+ | HLL '(' ')'
+// { ldemul_hll((char *)NULL); }
+ ;
+
+high_level_library_NAME_list:
+ high_level_library_NAME_list opt_comma filename
+// { ldemul_hll($3); }
+ | filename
+// { ldemul_hll($1); }
+
+ ;
+
+low_level_library:
+ SYSLIB '(' low_level_library_NAME_list ')'
+ ; low_level_library_NAME_list:
+ low_level_library_NAME_list opt_comma filename
+// { ldemul_syslib($3); }
+ |
+ ;
+
+floating_point_support:
+ FLOAT
+// { lang_float(TRUE); }
+ | NOFLOAT
+// { lang_float(FALSE); }
+ ;
+
+nocrossref_list:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | NAME nocrossref_list
+// {
+// struct lang_nocrossref *n;
+//
+// n = (struct lang_nocrossref *) xmalloc (sizeof *n);
+// n->name = $1;
+// n->next = $2;
+// $$ = n;
+// }
+ | NAME ',' nocrossref_list
+// {
+// struct lang_nocrossref *n;
+//
+// n = (struct lang_nocrossref *) xmalloc (sizeof *n);
+// n->name = $1;
+// n->next = $3;
+// $$ = n;
+// }
+ ;
+
+mustbe_exp: // { ldlex_expression (); }
+ exp
+ // { ldlex_popstate (); $$=$2;}
+ ;
+
+exp :
+ '-' exp # expNegate // TODO: %prec UNARY
+// { $$ = exp_unop ('-', $2); }
+ | '(' exp ')' # expParen
+// { $$ = $2; }
+ | NEXT '(' exp ')' # expNextParen // TODO: %prec UNARY
+// { $$ = exp_unop ((int) $1,$3); }
+ | '!' exp # expInvert // TODO: %prec UNARY
+// { $$ = exp_unop ('!', $2); }
+ | '+' exp # expPlus // TODO: %prec UNARY
+// { $$ = $2; }
+ | '~' exp # expMinus // TODO: %prec UNARY
+// { $$ = exp_unop ('~', $2);}
+ | exp '*' exp # expMul
+// { $$ = exp_binop ('*', $1, $3); }
+ | exp '/' exp # expDiv
+// { $$ = exp_binop ('/', $1, $3); }
+ | exp '%' exp # expMod
+// { $$ = exp_binop ('%', $1, $3); }
+ | exp '+' exp # expAdd
+// { $$ = exp_binop ('+', $1, $3); }
+ | exp '-' exp # expSub
+// { $$ = exp_binop ('-' , $1, $3); }
+ | exp LSHIFT exp # expLshift
+// { $$ = exp_binop (LSHIFT , $1, $3); }
+ | exp RSHIFT exp # expRshift
+// { $$ = exp_binop (RSHIFT , $1, $3); }
+ | exp EQ exp # expEq
+// { $$ = exp_binop (EQ , $1, $3); }
+ | exp NE exp # expNe
+// { $$ = exp_binop (NE , $1, $3); }
+ | exp LE exp # expLe
+// { $$ = exp_binop (LE , $1, $3); }
+ | exp GE exp # expGe
+// { $$ = exp_binop (GE , $1, $3); }
+ | exp '<' exp # expGt
+// { $$ = exp_binop ('<' , $1, $3); }
+ | exp '>' exp # expLt
+// { $$ = exp_binop ('>' , $1, $3); }
+ | exp '&' exp # expAnd
+// { $$ = exp_binop ('&' , $1, $3); }
+ | exp '^' exp # expXor
+// { $$ = exp_binop ('^' , $1, $3); }
+ | exp '|' exp # expOr
+// { $$ = exp_binop ('|' , $1, $3); }
+ | exp '?' exp ':' exp # expTrinary
+// { $$ = exp_trinop ('?' , $1, $3, $5); }
+ | exp ANDAND exp # expAndand
+// { $$ = exp_binop (ANDAND , $1, $3); }
+ | exp OROR exp # expOror
+// { $$ = exp_binop (OROR , $1, $3); }
+ | DEFINED '(' NAME ')' # expDefined
+// { $$ = exp_nameop (DEFINED, $3); }
+ | INT # expInt
+// { $$ = exp_bigintop ($1.integer, $1.str); }
+ | SIZEOF_HEADERS # expSizeofHeaders
+// { $$ = exp_nameop (SIZEOF_HEADERS,0); }
+ | ALIGNOF '(' NAME ')' # expAlignof
+// { $$ = exp_nameop (ALIGNOF,$3); }
+ | SIZEOF '(' NAME ')' # expSizeof
+// { $$ = exp_nameop (SIZEOF,$3); }
+ | ADDR '(' NAME ')' # expAddr
+// { $$ = exp_nameop (ADDR,$3); }
+ | LOADADDR '(' NAME ')' # expLoadaddr
+// { $$ = exp_nameop (LOADADDR,$3); }
+ | CONSTANT '(' NAME ')' # expConstant
+// { $$ = exp_nameop (CONSTANT,$3); }
+ | ABSOLUTE '(' exp ')' # expAbsolute
+// { $$ = exp_unop (ABSOLUTE, $3); }
+ | ALIGN_K '(' exp ')' # expAlign
+// { $$ = exp_unop (ALIGN_K,$3); }
+ | ALIGN_K '(' exp ',' exp ')' # expAlign2
+// { $$ = exp_binop (ALIGN_K,$3,$5); }
+ | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' # expDataSegmentAlign
+// { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
+ | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' # expDataSegmentRelRoEnd
+// { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3);
+ | DATA_SEGMENT_END '(' exp ')' # expDataSegmentEnd
+// { $$ = exp_unop (DATA_SEGMENT_END, $3); }
+ | SEGMENT_START '(' NAME ',' exp ')' # expSegmentStart
+// { /* The operands to the expression node are
+// placed in the opposite order from the way
+// in which they appear in the script as
+// that allows us to reuse more code in
+// fold_binary. */
+// $$ = exp_binop (SEGMENT_START,
+// $5,
+// exp_nameop (NAME, $3)); }
+ | BLOCK '(' exp ')' # expBlock
+// { $$ = exp_unop (ALIGN_K,$3); }
+ | NAME # expName
+// { $$ = exp_nameop (NAME,$1); }
+ | MAX_K '(' exp ',' exp ')' # expMax
+// { $$ = exp_binop (MAX_K, $3, $5 ); }
+ | MIN_K '(' exp ',' exp ')' # expMin
+// { $$ = exp_binop (MIN_K, $3, $5 ); }
+ | ASSERT_K '(' exp ',' NAME ')' # expAssert
+// { $$ = exp_assert ($3, $5); }
+ | ORIGIN '(' NAME ')' # expOrigin
+// { $$ = exp_nameop (ORIGIN, $3); }
+ | LENGTH '(' NAME ')' # expLengthExp
+// { $$ = exp_nameop (LENGTH, $3); }
+ | LOG2CEIL '(' exp ')' # expLog2ceil
+// { $$ = exp_unop (LOG2CEIL, $3); }
+ ;
+
+
+memspec_at_opt:
+ AT '>' NAME // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_at:
+ AT '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_align:
+ ALIGN_K '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_align_with_input:
+ ALIGN_WITH_INPUT // { $$ = ALIGN_WITH_INPUT; }
+ | // { $$ = 0; }
+ ;
+
+opt_subalign:
+ SUBALIGN '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+sect_constraint:
+ ONLY_IF_RO // { $$ = ONLY_IF_RO; }
+ | ONLY_IF_RW // { $$ = ONLY_IF_RW; }
+ | SPECIAL // { $$ = SPECIAL; }
+ | // { $$ = 0; }
+ ;
+
+section: NAME // { ldlex_expression(); }
+ opt_exp_with_type
+ opt_at
+ opt_align
+ opt_align_with_input
+ opt_subalign // { ldlex_popstate (); ldlex_script (); }
+ sect_constraint
+ '{'
+// {
+// lang_enter_output_section_statement($1, $3,
+// sectype,
+// $5, $7, $4, $9, $6);
+// }
+ statement_list_opt
+ '}' // { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_output_section_statement ($18, $15, $17, $16);
+// }
+ opt_comma
+ {}
+ | OVERLAY
+// { ldlex_expression (); }
+ opt_exp_without_type opt_nocrossrefs opt_at opt_subalign
+// { ldlex_popstate (); ldlex_script (); }
+ '{'
+// {
+// lang_enter_overlay ($3, $6);
+// }
+ overlay_section
+ '}'
+// { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_overlay ($5, (int) $4,
+// $16, $13, $15, $14);
+// }
+ opt_comma
+ | /* The GROUP case is just enough to support the gcc
+ svr3.ifile script. It is not intended to be full
+ support. I'm not even sure what GROUP is supposed
+ to mean. */
+ GROUP // { ldlex_expression (); }
+ opt_exp_with_type
+// {
+// ldlex_popstate ();
+// lang_add_assignment (exp_assign (".", $3, FALSE));
+// }
+ '{' sec_or_group_p1 '}'
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ sec_or_group_p1 END
+ // { ldlex_popstate (); }
+ ;
+
+type:
+ NOLOAD // { sectype = noload_section; }
+ | DSECT // { sectype = noalloc_section; }
+ | COPY // { sectype = noalloc_section; }
+ | INFO // { sectype = noalloc_section; }
+ | OVERLAY // { sectype = noalloc_section; }
+ ;
+
+atype:
+ '(' type ')'
+ | /* EMPTY */ // { sectype = normal_section; }
+ | '(' ')' // { sectype = normal_section; }
+ ;
+
+opt_exp_with_type:
+ exp atype ':' // { $$ = $1; }
+ | atype ':' // { $$ = (etree_type *)NULL; }
+ | /* The BIND cases are to support the gcc svr3.ifile
+ script. They aren't intended to implement full
+ support for the BIND keyword. I'm not even sure
+ what BIND is supposed to mean. */
+ BIND '(' exp ')' atype ':' // { $$ = $3; }
+ | BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
+ // { $$ = $3; }
+ ;
+
+opt_exp_without_type:
+ exp ':' // { $$ = $1; }
+ | ':' // { $$ = (etree_type *) NULL; }
+ ;
+
+opt_nocrossrefs:
+ /* empty */
+// { $$ = 0; }
+ | NOCROSSREFS
+// { $$ = 1; }
+ ;
+
+memspec_opt:
+ '>' NAME
+ // { $$ = $2; }
+ | // { $$ = DEFAULT_MEMORY_REGION; }
+ ;
+
+phdr_opt:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | phdr_opt ':' NAME
+// {
+// struct lang_output_section_phdr_list *n;
+//
+// n = ((struct lang_output_section_phdr_list *)
+// xmalloc (sizeof *n));
+// n->name = $3;
+// n->used = FALSE;
+// n->next = $1;
+// $$ = n;
+// }
+ ;
+
+overlay_section:
+ /* empty */
+ | overlay_section
+ NAME
+// {
+// ldlex_script ();
+// lang_enter_overlay_section ($2);
+// }
+ '{' statement_list_opt '}'
+// { ldlex_popstate (); ldlex_expression (); }
+ phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_overlay_section ($9, $8);
+// }
+ opt_comma
+ ;
+
+phdrs:
+ PHDRS '{' phdr_list '}'
+ ;
+
+phdr_list:
+ /* empty */
+ | phdr_list phdr
+ ;
+
+phdr:
+ NAME // { ldlex_expression (); }
+ phdr_type phdr_qualifiers // { ldlex_popstate (); }
+ ';'
+// {
+// lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
+// $4.flags);
+// }
+ ;
+
+phdr_type:
+ exp
+// {
+// $$ = $1;
+//
+// if ($1->type.node_class == etree_name
+// && $1->type.node_code == NAME)
+// {
+// const char *s;
+// unsigned int i;
+// static const char * const phdr_types[] =
+// {
+// "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
+// "PT_INTERP", "PT_NOTE", "PT_SHLIB",
+// "PT_PHDR", "PT_TLS"
+// };
+//
+// s = $1->name.name;
+// for (i = 0;
+// i < sizeof phdr_types / sizeof phdr_types[0];
+// i++)
+// if (strcmp (s, phdr_types[i]) == 0)
+// {
+// $$ = exp_intop (i);
+// break;
+// }
+// if (i == sizeof phdr_types / sizeof phdr_types[0])
+// {
+// if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
+// $$ = exp_intop (0x6474e550);
+// else if (strcmp (s, "PT_GNU_STACK") == 0)
+// $$ = exp_intop (0x6474e551);
+// else
+// {
+// einfo (_("\
+//%X%P:%S: unknown phdr type `%s' (try integer literal)\n"),
+// NULL, s);
+// $$ = exp_intop (0);
+// }
+// }
+// }
+// }
+ ;
+
+phdr_qualifiers:
+ /* empty */
+// {
+// memset (&$$, 0, sizeof (struct phdr_info));
+// }
+ | NAME phdr_val phdr_qualifiers
+// {
+// $$ = $3;
+// if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
+// $$.filehdr = TRUE;
+// else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
+// $$.phdrs = TRUE;
+// else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
+// $$.flags = $2;
+// else
+// einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"),
+// NULL, $1);
+// }
+ | AT '(' exp ')' phdr_qualifiers
+// {
+// $$ = $5;
+// $$.at = $3;
+// }
+ ;
+
+phdr_val:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | '(' exp ')'
+// {
+// $$ = $2;
+// }
+ ;
+
+dynamic_list_file:
+// {
+// ldlex_version_file ();
+// PUSH_ERROR (_("dynamic list"));
+// }
+ dynamic_list_nodes
+// {
+// ldlex_popstate ();
+// POP_ERROR ();
+// }
+ ;
+
+dynamic_list_nodes:
+ dynamic_list_node
+ | dynamic_list_nodes dynamic_list_node
+ ;
+
+dynamic_list_node:
+ '{' dynamic_list_tag '}' ';'
+ ;
+
+dynamic_list_tag:
+ vers_defns ';'
+// {
+// lang_append_dynamic_list ($1);
+// }
+ ;
+
+/* This syntax is used within an external version script file. */
+
+version_script_file:
+// {
+// ldlex_version_file ();
+// PUSH_ERROR (_("VERSION script"));
+// }
+ vers_nodes
+// {
+// ldlex_popstate ();
+// POP_ERROR ();
+// }
+ ;
+
+/* This is used within a normal linker script file. */
+
+version:
+// {
+// ldlex_version_script ();
+// }
+ VERSIONK '{' vers_nodes '}'
+// {
+// ldlex_popstate ();
+// }
+ ;
+
+vers_nodes:
+ vers_node
+ | vers_nodes vers_node
+ ;
+
+vers_node:
+ '{' vers_tag '}' ';'
+// {
+// lang_register_vers_node (NULL, $2, NULL);
+// }
+ | VERS_TAG '{' vers_tag '}' ';'
+// {
+// lang_register_vers_node ($1, $3, NULL);
+// }
+ | VERS_TAG '{' vers_tag '}' verdep ';'
+// {
+// lang_register_vers_node ($1, $3, $5);
+// }
+ ;
+
+verdep:
+ VERS_TAG
+// {
+// $$ = lang_add_vers_depend (NULL, $1);
+// }
+ | verdep VERS_TAG
+// {
+// $$ = lang_add_vers_depend ($1, $2);
+// }
+ ;
+
+vers_tag:
+ /* empty */
+// {
+// $$ = lang_new_vers_node (NULL, NULL);
+// }
+ | vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($1, NULL);
+// }
+ | GLOBAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($3, NULL);
+// }
+ | LOCAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node (NULL, $3);
+// }
+ | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($3, $7);
+// }
+ ;
+
+vers_defns:
+ VERS_IDENTIFIER
+// {
+// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE);
+// }
+ | NAME
+// {
+// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE);
+// }
+ | vers_defns ';' VERS_IDENTIFIER
+// {
+// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' NAME
+// {
+// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE);
+// }
+ | vers_defns ';' EXTERN NAME '{'
+// {
+// $<name>$ = ldgram_vers_current_lang;
+// ldgram_vers_current_lang = $4;
+// }
+ vers_defns opt_semicolon '}'
+// {
+// struct bfd_elf_version_expr *pat;
+// for (pat = $7; pat->next != NULL; pat = pat->next);
+// pat->next = $1;
+// $$ = $7;
+// ldgram_vers_current_lang = $<name>6;
+// }
+ | EXTERN NAME '{'
+// {
+// $<name>$ = ldgram_vers_current_lang;
+// ldgram_vers_current_lang = $2;
+// }
+ vers_defns opt_semicolon '}'
+// {
+// $$ = $5;
+// ldgram_vers_current_lang = $<name>4;
+// }
+ | GLOBAL
+// {
+// $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' GLOBAL
+// {
+// $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE);
+// }
+ | LOCAL
+// {
+// $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' LOCAL
+// {
+// $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE);
+// }
+ | EXTERN
+// {
+// $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' EXTERN
+// {
+// $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
+// }
+ ;
+
+opt_semicolon:
+ /* empty */
+ | ';'
+ ;
+
+//%token <token>
+LBRACE : '{';
+RBRACE : '}';
+
+// <integer>
+// <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
+// <name> filename
+//%type <versyms> vers_defns
+//%type <versnode> vers_tag
+//%type <deflist> verdep
+
+ABSOLUTE : 'ABSOLUTE';
+ADDR : 'ADDR';
+AFTER : 'AFTER';
+ALIAS : 'ALIAS';
+ALIGN : 'ALIGN';
+ALIGN_K : 'ALIGN';
+ALIGNMOD : 'ALIGNMOD';
+ALIGNOF : 'ALIGNOF';
+ALIGN_WITH_INPUT : 'ALIGN_WITH_INPUT';
+AS_NEEDED : 'AS_NEEDED';
+ASSERT_K : 'ASSERT';
+AT : 'AT';
+BASE : 'BASE';
+BEFORE : 'BEFORE';
+BIND : 'BIND';
+BLOCK : 'BLOCK';
+BYTE : 'BYTE';
+CASE : 'CASE';
+CHIP : 'CHIP';
+CONSTANT : 'CONSTANT';
+CONSTRUCTORS : 'CONSTRUCTORS';
+COPY : 'COPY';
+CREATE_OBJECT_SYMBOLS : 'CREATE_OBJECT_SYMBOLS';
+DATA_SEGMENT_ALIGN : 'DATA_SEGMENT_ALIGN';
+DATA_SEGMENT : 'DATA_SEGMENT';
+DATA_SEGMENT_END : 'DATA_SEGMENT_END';
+DATA_SEGMENT_RELRO_END : 'DATA_SEGMENT_RELRO_END';
+DEFINED : 'DEFINED';
+DEFSYMEND : 'DEFSYMEND';
+DSECT : 'DSECT';
+ENDWORD : 'ENDWORD';
+ENTRY : 'ENTRY';
+EXCLUDE_FILE : 'EXCLUDE_FILE';
+EXTERN : 'EXTERN';
+FILL : 'FILL';
+FLOAT : 'FLOAT';
+FORCE_COMMON_ALLOCATION : 'FORCE_COMMON_ALLOCATION';
+FORMAT : 'FORMAT';
+GLOBAL : 'GLOBAL';
+GROUP : 'GROUP';
+HIDDEN_ : 'HIDDEN';
+HLL : 'HLL';
+INCLUDE : 'INCLUDE';
+INFO : 'INFO';
+INHIBIT_COMMON_ALLOCATION : 'INHIBIT_COMMON_ALLOCATION';
+//INPUT_DEFSYM : 'INPUT_DEFSYM';
+//INPUT_DYNAMIC_LIST : 'INPUT_DYNAMIC_LIST';
+INPUT : 'INPUT';
+//INPUT_MRI_SCRIPT : 'INPUT_MRI_SCRIPT';
+//INPUT_SCRIPT : 'INPUT_SCRIPT';
+//INPUT_SECTION_FLAGS : 'INPUT_SECTION_FLAGS';
+//INPUT_VERSION_SCRIPT : 'INPUT_VERSION_SCRIPT';
+INSERT_K : 'INSERT';
+KEEP : 'KEEP';
+LD_FEATURE : 'LD_FEATURE';
+LENGTH : 'LENGTH';
+LIST : 'LIST';
+LOADADDR : 'LOADADDR';
+LOAD : 'LOAD';
+LOCAL : 'LOCAL';
+LOG2CEIL : 'LOG2CEIL';
+LONG : 'LONG';
+MAP : 'MAP';
+MAX_K : 'MAX';
+MEMORY : 'MEMORY';
+MIN_K : 'MIN';
+NAMEWORD : 'NAMEWORD';
+NEWLINE : 'NEWLINE';
+NEXT : 'NEXT';
+NOCROSSREFS : 'NOCROSSREFS';
+NOCROSSREFS_TO : 'NOCROSSREFS_TO';
+NOFLOAT : 'NOFLOAT';
+NOLOAD : 'NOLOAD';
+ONLY_IF_RO : 'ONLY_IF_RO';
+ONLY_IF_RW : 'ONLY_IF_RW';
+ORDER : 'ORDER';
+ORIGIN : 'ORIGIN'; // TODO: or 'org' or 'o'.
+OUTPUT_ARCH : 'OUTPUT_ARCH';
+OUTPUT_FORMAT : 'OUTPUT_FORMAT';
+OUTPUT : 'OUTPUT';
+OVERLAY : 'OVERLAY';
+PHDRS : 'PHDRS';
+PROVIDE_HIDDEN : 'PROVIDE_HIDDEN';
+PROVIDE : 'PROVIDE';
+PUBLIC : 'PUBLIC';
+QUAD : 'QUAD';
+REGION_ALIAS : 'REGION_ALIAS';
+REL : 'REL';
+SEARCH_DIR : 'SEARCH_DIR';
+SECTIONS : 'SECTIONS';
+SECT : 'SECT';
+SEGMENT_START : 'SEGMENT_START';
+SHORT : 'SHORT';
+SIZEOF_HEADERS : 'SIZEOF_HEADERS';
+SIZEOF : 'SIZEOF';
+SORT_BY_ALIGNMENT : 'SORT_BY_ALIGNMENT';
+SORT_BY_INIT_PRIORITY : 'SORT_BY_INIT_PRIORITY';
+SORT_BY_NAME : 'SORT_BY_NAME';
+SORT_NONE : 'SORT_NONE';
+SPECIAL : 'SPECIAL';
+SQUAD : 'SQUAD';
+START : 'START';
+STARTUP : 'STARTUP';
+SUBALIGN : 'SUBALIGN';
+SYSLIB : 'SYSLIB';
+TARGET_K : 'TARGET';
+TRUNCATE : 'TRUNCATE';
+VERS_IDENTIFIER : 'VERS_IDENTIFIER';
+VERSIONK : 'VERSIONK';
+VERS_TAG : 'VERS_TAG';
+
+/*
+Names are very liberal, they can be full strings and start with a dot.
+*/
+
+NAME : [\._a-zA-Z][_a-zA-Z0-9]*;
+
+// TODO: ld supports some really fancy expressions here, like "0101010b", "ffH", "ffx", "$Aa" etc
+//INT : '0x' [0-9a-fA-F]+
+// | [0-9]+;
+INT : INT_NUMBER INT_SIZE?;
+INT_NUMBER : INT_HEX
+ | INT_DECIMAL;
+INT_HEX : '0x' [0-9a-fA-F]+;
+INT_DECIMAL : [0-9]+;
+INT_SIZE : 'M' | 'm' | 'K' | 'k';
+
+END : 'END';
+
+LNAME : '-l' NAME;
+PLUSEQ : '+=';
+MINUSEQ : '-=';
+MULTEQ : '*=';
+DIVEQ : '/=';
+LSHIFTEQ : '<<=';
+RSHIFTEQ : '>>=';
+ANDEQ : '&=';
+OREQ : '|=';
+LSHIFT : '<<';
+RSHIFT : '>>';
+EQ : '=';
+NE : '!=';
+LE : '<=';
+GE : '>=';
+ANDAND : '&&';
+OROR : '||';
+
+BlockComment
+ : '/*' .*? '*/' -> skip
+ ;
+
+WS : [ \t\r\n]+ -> skip ;
diff --git a/cmake/elfinfo/Makefile.grammar b/cmake/elfinfo/Makefile.grammar
new file mode 100644
index 0000000..13eb13d
--- /dev/null
+++ b/cmake/elfinfo/Makefile.grammar
@@ -0,0 +1,53 @@
+GRAMMAR=GnuLd.g4
+G4_PACKAGE ?= io.trygvis.ld.antlr
+PACKAGE_PATH = $(subst .,/,$(G4_PACKAGE))
+
+G4_JAVA=\
+ $(patsubst %.g4,antlr/$(PACKAGE_PATH)/%Lexer.java,$(GRAMMAR))
+
+# $(patsubst %.g4,antlr/$(PACKAGE_PATH)/%Parser.java,$(GRAMMAR)) \
+# $(patsubst %.g4,antlr/$(PACKAGE_PATH)/%Listener.java,$(GRAMMAR)) \
+# $(patsubst %.g4,antlr/$(PACKAGE_PATH)/%BaseListener.java,$(GRAMMAR))
+
+G4_CLASSES=$(patsubst antlr/%.java,target/classes/%.class,$(G4_JAVA))
+
+ANTLR_URL=http://repo1.maven.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar
+ANTLR_RUNTIME_URL=http://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.jar
+ANTLR_JAR=$(notdir $(ANTLR_URL))
+ANTLR_RUNTIME_JAR=$(notdir $(ANTLR_RUNTIME_URL))
+
+all: meta-java
+
+meta-java: $(G4_JAVA)
+
+meta-classes: $(G4_CLASSES)
+
+info:
+ @echo "ANTLR_JAR $(ANTLR_JAR)"
+ @echo "GRAMMAR $(GRAMMAR)"
+ @echo "G4_JAVA $(G4_JAVA)"
+ @echo "G4_CLASSES $(G4_CLASSES)"
+
+target/classes antlr:
+ mkdir -p $@
+
+download: $(ANTLR_JAR) $(ANTLR_RUNTIME_JAR)
+
+$(ANTLR_JAR):
+ wget $(ANTLR_URL)
+
+$(ANTLR_RUNTIME_JAR):
+ wget $(ANTLR_RUNTIME_URL)
+
+$(G4_JAVA): $(GRAMMAR) | antlr $(ANTLR_JAR)
+ java -cp $(ANTLR_JAR) org.antlr.v4.Tool \
+ -visitor \
+ -o antlr/$(PACKAGE_PATH) \
+ $(patsubst %,-package %,$(G4_PACKAGE)) \
+ $<
+
+$(G4_CLASSES): $(G4_JAVA) | target/classes
+ javac -d target/classes -cp $(ANTLR_JAR) $(wildcard antlr/$(PACKAGE_PATH)/*.java)
+
+clean:
+ rm -rf target/classes antlr
diff --git a/cmake/elfinfo/grun.sh b/cmake/elfinfo/grun.sh
new file mode 100755
index 0000000..ccd4743
--- /dev/null
+++ b/cmake/elfinfo/grun.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+url="http://repo1.maven.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar"
+jar="$(basename $url)"
+
+if [[ ! -r "$jar" ]]
+then
+ wget "$url"
+fi
+
+CLASSPATH="$CLASSPATH:$jar"
+CLASSPATH="$CLASSPATH:target/classes"
+export CLASSPATH
+exec java org.antlr.v4.gui.TestRig "$@"
diff --git a/cmake/elfinfo/lds/d2000.ld b/cmake/elfinfo/lds/d2000.ld
new file mode 100644
index 0000000..ef253c6
--- /dev/null
+++ b/cmake/elfinfo/lds/d2000.ld
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ENTRY(_start)
+
+MEMORY
+{
+ flash(r) : ORIGIN = 0x00180000, LENGTH = 32K
+ data(rw) : ORIGIN = 0x00200000, LENGTH = 4K
+ /* Place IDT at the bottom of SRAM, 52 gate wide */
+ esram_idt (rw) : ORIGIN = 0x00280000, LENGTH = 0x1A0
+ esram(rw) : ORIGIN = 0x002801A0, LENGTH = 8K - 1K - 0x1A0
+ stack(rw) : ORIGIN = 0x00281C00, LENGTH = 1K
+}
+
+/* IDT definition */
+__idt_start = ORIGIN(esram_idt);
+__idt_end = __idt_start + LENGTH(esram_idt);
+
+SECTIONS
+{
+ .text :
+ {
+ *(.text.entry)
+ *(.text)
+ *(.text.last)
+ *(.text.*)
+ } >flash
+
+ .rodata :
+ {
+ *(.rdata*)
+ *(.rodata*)
+ } >flash
+
+ .data :
+ {
+ *(.data*)
+ } >esram AT>flash
+
+ .bss :
+ {
+ *(.bss*)
+ *(COMMON)
+ } >esram AT>esram
+
+ /* Symbols for C runtime init code. */
+ __data_lma = LOADADDR(.data);
+ __data_vma = ADDR(.data);
+ __data_size = SIZEOF(.data);
+ __bss_start = ADDR(.bss);
+ __bss_end = __bss_start + SIZEOF(.bss);
+
+ /* Heap */
+ __heap = .;
+ __heap_end = ORIGIN(stack);
+
+ .comment 0 : { *(.comment) }
+}
diff --git a/cmake/elfinfo/lds/stm32.ld b/cmake/elfinfo/lds/stm32.ld
new file mode 100644
index 0000000..bafd520
--- /dev/null
+++ b/cmake/elfinfo/lds/stm32.ld
@@ -0,0 +1,62 @@
+ENTRY(_Reset_Handler)
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20k
+ MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
+}
+
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+
+SECTIONS
+{
+ /* Put the ISR section at the start of the flash area */
+ .isr :
+ {
+ /* The first word has to be the initial stack pointer */
+ LONG(__initial_stack_pointer);
+ KEEP(*/init_high.cpp.obj(.isr_vectors))
+ } >FLASH
+ ASSERT(SIZEOF(.isr) > 100, "The isr_vectors section is too small")
+ ASSERT(SIZEOF(.isr) < 1000, "The isr_vectors section is too big")
+ ASSERT(ADDR(.isr) == ORIGIN(FLASH), "The isr_vectors section was not placed at the start of the flash area")
+
+ .text :
+ {
+ *(.text)
+ KEEP(*(.text.*))
+ *(.rodata*)
+ } >FLASH
+
+ .init_arrays :
+ {
+ _init_array_start = .;
+ KEEP(*(.init_array))
+ KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+ _init_array_end = .;
+ } >FLASH
+
+ . = ORIGIN(RAM);
+
+ .data ALIGN(4) :
+ {
+ *(.data)
+ *(.data.*)
+ } >RAM AT >FLASH
+
+ .bss ALIGN(4) (NOLOAD) :
+ {
+ *(.bss)
+ *(.bss.*)
+ } >RAM
+
+ _copy_data_store = ADDR(.data);
+ _copy_data_store_end = _copy_data_store + SIZEOF(.data);
+ _copy_data_load = LOADADDR(.data);
+
+ _bss_start = ADDR(.bss);
+ _bss_end = _bss_start + SIZEOF(.bss);
+
+ __initial_stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 1;
+}
diff --git a/cmake/elfinfo/pom.xml b/cmake/elfinfo/pom.xml
new file mode 100644
index 0000000..bb46e6f
--- /dev/null
+++ b/cmake/elfinfo/pom.xml
@@ -0,0 +1,34 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.trygvis.ld</groupId>
+ <artifactId>ld</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4</artifactId>
+ <version>4.5.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>4.5.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
new file mode 100644
index 0000000..f827a8b
--- /dev/null
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
@@ -0,0 +1,483 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdBaseVisitor;
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRFileStream;
+import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class LdScript {
+
+ public enum MemoryAttribute {
+ R, W, X, A, I,
+ }
+
+ public static class MemoryArea {
+ private final BigInteger MEGA = BigInteger.valueOf(1024 * 1024);
+ private final BigInteger KILO = BigInteger.valueOf(1024);
+
+ String name;
+ BigInteger origin;
+ BigInteger length;
+ Set<MemoryAttribute> attributes;
+
+ @Override
+ public String toString() {
+ return "MemoryArea{" +
+ "name='" + name + '\'' +
+ ", origin=" + origin +
+ ", length=" + length +
+ ", attributes='" + attributes + '\'' +
+ '}';
+ }
+
+ public String prettyOrigin() {
+ if (origin == null) {
+ return "";
+ }
+ String hex = origin.toString(16);
+
+ return "0x" + ("00000000").substring(0, 8 - hex.length()) + hex;
+ }
+
+ public String prettyLength() {
+ if (length == null) {
+ return "";
+ }
+
+ if (length.compareTo(MEGA) >= 0 && length.mod(MEGA).equals(BigInteger.ZERO)) {
+ return length.divide(MEGA) + "M";
+ }
+
+ if (length.compareTo(KILO) >= 0 && length.mod(KILO).equals(BigInteger.ZERO)) {
+ return length.divide(KILO) + "k";
+ }
+
+ return String.valueOf(length);
+ }
+
+ public String prettyAttributes() {
+ String s = "";
+ for (MemoryAttribute attribute : attributes) {
+ s += attribute.name().toLowerCase();
+ }
+ return s;
+ }
+ }
+
+ public static class Section {
+ String name;
+ }
+
+ public static void main(String[] args) throws Exception {
+ try {
+ work(args);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private static void work(String[] args) throws Exception {
+ args = new String[]{"lds/d2000.ld"};
+
+ GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(args[0]));
+ GnuLdParser parser = new GnuLdParser(new BufferedTokenStream(lexer));
+
+// ElfInfoGnuLdBaseListener listener = new ElfInfoGnuLdBaseListener();
+// parser.addParseListener(listener);
+//
+// parser.file();
+//
+// for (Section section : listener.sections) {
+// System.out.println("section.name = " + section.name);
+// }
+
+ ElfinfoGnuLdBaseVisitor visitor = new ElfinfoGnuLdBaseVisitor();
+ visitor.visit(parser.file());
+
+ System.out.println("--------------------------------------------------------");
+ for (MemoryArea area : visitor.memoryAreas) {
+ System.out.println(" " + area.name + "(" + area.prettyAttributes() + ") : ORIGIN = " + area.prettyOrigin() + ", LENGTH=" + area.prettyLength());
+ }
+ }
+
+ private static class ElfinfoExprGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoExprGnuLdBaseVisitor> {
+ private BigInteger value;
+ private ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ public static BigInteger evaluate(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprGnuLdBaseVisitor v = new ElfinfoExprGnuLdBaseVisitor();
+ v.visitMustbe_exp(ctx);
+ return v.value();
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLt(GnuLdParser.ExpLtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpBlock(GnuLdParser.ExpBlockContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAbsolute(GnuLdParser.ExpAbsoluteContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLog2ceil(GnuLdParser.ExpLog2ceilContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpDataSegmentEnd(GnuLdParser.ExpDataSegmentEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpSub(GnuLdParser.ExpSubContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitExpSub");
+
+ ElfinfoExprGnuLdBaseVisitor ret = visitChildren(ctx);
+ BigInteger a = es.removeFrom(ctx.exp(0));
+ BigInteger b = es.removeFrom(ctx.exp(1));
+
+ BigInteger x = a.subtract(b);
+
+ es.put(ctx, x);
+ return ret;
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpDefined(GnuLdParser.ExpDefinedContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpMod(GnuLdParser.ExpModContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpInvert(GnuLdParser.ExpInvertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAlign(GnuLdParser.ExpAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpMul(GnuLdParser.ExpMulContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAnd(GnuLdParser.ExpAndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpXor(GnuLdParser.ExpXorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpParen(GnuLdParser.ExpParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpMinus(GnuLdParser.ExpMinusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpDiv(GnuLdParser.ExpDivContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpGe(GnuLdParser.ExpGeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpMin(GnuLdParser.ExpMinContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAlign2(GnuLdParser.ExpAlign2Context ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpNegate(GnuLdParser.ExpNegateContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpName(GnuLdParser.ExpNameContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpOr(GnuLdParser.ExpOrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpTrinary(GnuLdParser.ExpTrinaryContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpOror(GnuLdParser.ExpOrorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpDataSegmentAlign(GnuLdParser.ExpDataSegmentAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLoadaddr(GnuLdParser.ExpLoadaddrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpGt(GnuLdParser.ExpGtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpEq(GnuLdParser.ExpEqContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpMax(GnuLdParser.ExpMaxContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLshift(GnuLdParser.ExpLshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpSizeofHeaders(GnuLdParser.ExpSizeofHeadersContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpLe(GnuLdParser.ExpLeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpNe(GnuLdParser.ExpNeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAndand(GnuLdParser.ExpAndandContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpRshift(GnuLdParser.ExpRshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpNextParen(GnuLdParser.ExpNextParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAlignof(GnuLdParser.ExpAlignofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpSegmentStart(GnuLdParser.ExpSegmentStartContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpInt(GnuLdParser.ExpIntContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitExpInt");
+
+ String str = ctx.INT().getText().toLowerCase();
+ int base = 10;
+ if (str.startsWith("0x")) {
+ base = 16;
+ str = str.substring(2);
+ }
+
+ int factor = 1;
+ if (str.endsWith("k")) {
+ factor = 1024;
+ str = str.substring(0, str.length() - 1);
+ } else if (str.endsWith("k")) {
+ factor = 1024 * 1024;
+ str = str.substring(0, str.length() - 1);
+ }
+
+ BigInteger i = new BigInteger(str, base);
+ if (factor > 1) {
+ i = i.multiply(BigInteger.valueOf(factor));
+ }
+ System.out.println("ctx = " + ctx);
+ System.out.println("i = " + i);
+ es.put(ctx, i);
+
+ return this;
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpConstant(GnuLdParser.ExpConstantContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpPlus(GnuLdParser.ExpPlusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpDataSegmentRelRoEnd(GnuLdParser.ExpDataSegmentRelRoEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitExpAssert(GnuLdParser.ExpAssertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprGnuLdBaseVisitor visitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprGnuLdBaseVisitor ret = visitChildren(ctx);
+
+ value = es.removeFrom(ctx.exp());
+ es.put(ctx, value);
+
+ return ret;
+ }
+
+ public BigInteger value() {
+ if (value != null) {
+ return value;
+ }
+
+ throw new RuntimeException("Something bad happened, probably an unevaluated expression part.");
+ }
+ }
+
+ private static class ElfinfoGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoGnuLdBaseVisitor> {
+ public List<MemoryArea> memoryAreas = new ArrayList<>();
+
+ public List<Section> sections = new ArrayList<>();
+
+ ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ @Override
+ public ElfinfoGnuLdBaseVisitor visitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitMemory_spec");
+ visitChildren(ctx);
+
+ if (attributesInverted) {
+ // not quite sure how this is supposed to work yet
+ throw new RuntimeException("Inverted memory region attributes is not implemented yet.");
+ }
+
+ MemoryArea ma = new MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+ ma.origin = ElfinfoExprGnuLdBaseVisitor.evaluate(ctx.origin_spec().mustbe_exp());
+ ma.length = ElfinfoExprGnuLdBaseVisitor.evaluate(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ return this;
+ }
+
+ MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<MemoryAttribute> attributes;
+
+ @Override
+ public ElfinfoGnuLdBaseVisitor visitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributes_opt");
+ attributes = new HashSet<>();
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdBaseVisitor visitAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeNormal");
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdBaseVisitor visitAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeInverted");
+ if (!attributes.isEmpty()) {
+ throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
+ }
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+
+ attributesInverted = true;
+ return visitChildren(ctx);
+ }
+ }
+}