From d2fe9a793c74406c36b698efab2fe5ba5931b4c2 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 28 May 2007 08:52:18 +0000 Subject: [PATCH] Fix #102: Permit non-standard macho section names. Two forms are legal ({} are replaceables): SECTION {segname} {sectname} SECTION {sectname} segname={segname} Also, SECTION {sectname} where sectname is unrecognized is also legal, defaults segname to __TEXT, and generates a warning. Contributed by: bird-yasm@anduin.net svn path=/trunk/yasm/; revision=1852 --- libyasm/valparam.c | 19 + libyasm/valparam.h | 16 + modules/objfmts/macho/macho-objfmt.c | 99 ++- .../objfmts/macho/tests/nasm32/Makefile.inc | 3 + .../macho/tests/nasm32/macho32-sect.asm | 9 + .../macho/tests/nasm32/macho32-sect.errwarn | 7 + .../macho/tests/nasm32/macho32-sect.hex | 789 ++++++++++++++++++ 7 files changed, 915 insertions(+), 27 deletions(-) create mode 100644 modules/objfmts/macho/tests/nasm32/macho32-sect.asm create mode 100644 modules/objfmts/macho/tests/nasm32/macho32-sect.errwarn create mode 100644 modules/objfmts/macho/tests/nasm32/macho32-sect.hex diff --git a/libyasm/valparam.c b/libyasm/valparam.c index 84cf984d..752ab7e3 100644 --- a/libyasm/valparam.c +++ b/libyasm/valparam.c @@ -353,6 +353,25 @@ yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line, return 0; } +int +yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg) +{ + /*@dependent@*/ /*@null@*/ const char *local; + char **s = (char **)data; + + if (*s) + yasm_xfree(*s); + if (!(local = yasm_vp_string(vp))) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a string or identifier"), + vp->val); + return -1; + } + *s = yasm__xstrdup(local); + return 0; +} + int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp, unsigned long line, void *data) diff --git a/libyasm/valparam.h b/libyasm/valparam.h index 9a2a1303..4a64a66f 100644 --- a/libyasm/valparam.h +++ b/libyasm/valparam.h @@ -340,6 +340,22 @@ int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line, int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line, void *data, uintptr_t arg); +/** Standard helper for yasm_dir_helper() that parses an string (or + * standalone identifier) parameter. + * The #yasm_dir_help structure that uses this function should have + * needsparam=1. The data parameter that is ultimately passed to this + * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off) + * must point to a char * initialized to NULL. + * \param obj unused + * \param vp valparam + * \param line unused + * \param data pointer to char * + * \param arg unused + * \return -1 on error, 0 otherwise. + */ +int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + /** Standard catch-all callback fro yasm_dir_helper(). Generates standard * warning for all valparams. * \param obj unused diff --git a/modules/objfmts/macho/macho-objfmt.c b/modules/objfmts/macho/macho-objfmt.c index 109c3f91..830fe5d1 100644 --- a/modules/objfmts/macho/macho-objfmt.c +++ b/modules/objfmts/macho/macho-objfmt.c @@ -281,8 +281,8 @@ typedef struct macho_reloc { typedef struct macho_section_data { /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */ long scnum; /* section number (0=first section) */ - const char *segname; /* segment name in file */ - const char *sectname; /* section name in file */ + /*@only@*/ char *segname; /* segment name in file */ + /*@only@*/ char *sectname; /* section name in file */ unsigned long flags; /* S_* flags */ unsigned long size; /* size of raw data (section data) in bytes */ unsigned long offset; /* offset in raw data within file in bytes */ @@ -720,9 +720,13 @@ macho_objfmt_is_section_label(yasm_symrec *sym) * If there is not a section, leave as debugging symbol. */ if (sect) { - if (strcmp(yasm_symrec_get_name(sym), - yasm_section_get_name(sect)) == 0) - return 1; /* don't store section names */ + /*@dependent@*/ /*@null@*/ macho_section_data *msd; + + msd = yasm_section_get_data(sect, &macho_section_data_cb); + if (msd) { + if (msd->sym == sym) + return 1; /* don't store section names */ + } } } return 0; @@ -872,14 +876,13 @@ macho_objfmt_output_symtable(yasm_symrec *sym, /*@null@*/ void *d) if (sect) { /*@dependent@*/ /*@null@*/ macho_section_data *msd; - if (strcmp(yasm_symrec_get_name(sym), - yasm_section_get_name(sect)) == 0) { - /* don't store section names */ - yasm_intnum_destroy(val); - return 0; - } msd = yasm_section_get_data(sect, &macho_section_data_cb); if (msd) { + if (msd->sym == sym) { + /* don't store section names */ + yasm_intnum_destroy(val); + return 0; + } scnum = msd->scnum; n_type = N_SECT; } else @@ -1249,8 +1252,8 @@ macho_objfmt_init_new_section(yasm_object *object, yasm_section *sect, data = yasm_xmalloc(sizeof(macho_section_data)); data->scnum = objfmt_macho->parse_scnum++; - data->segname = ""; - data->sectname = ""; + data->segname = yasm__xstrdup(""); + data->sectname = yasm__xstrdup(""); data->flags = S_REGULAR; data->size = 0; data->nreloc = 0; @@ -1270,11 +1273,12 @@ macho_objfmt_add_default_section(yasm_object *object) macho_section_data *msd; int isnew; - retval = yasm_object_get_general(object, ".text", 0, 0, 1, 0, &isnew, 0); + retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 0, 1, 0, + &isnew, 0); if (isnew) { msd = macho_objfmt_init_new_section(object, retval, ".text", 0); - msd->segname = "__TEXT"; - msd->sectname = "__text"; + msd->segname = yasm__xstrdup("__TEXT"); + msd->sectname = yasm__xstrdup("__text"); msd->flags = S_ATTR_PURE_INSTRUCTIONS; yasm_section_set_align(retval, 0, 0); yasm_section_set_default(retval, 1); @@ -1291,11 +1295,12 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, yasm_valparam *vp; yasm_section *retval; int isnew; - const char *f_segname, *f_sectname; + /*@only@*/ char *f_sectname; unsigned long flags; unsigned long align; int flags_override = 0; const char *sectname; + char *realname; int resonly = 0; macho_section_data *msd; size_t i; @@ -1366,14 +1371,18 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, }; struct macho_section_switch_data { + /*@only@*/ /*@null@*/ char *f_segname; /*@only@*/ /*@null@*/ yasm_intnum *align_intn; } data; static const yasm_dir_help help[] = { + { "segname", 1, yasm_dir_helper_string, + offsetof(struct macho_section_switch_data, f_segname), 0 }, { "align", 1, yasm_dir_helper_intn, offsetof(struct macho_section_switch_data, align_intn), 0 } }; + data.f_segname = NULL; data.align_intn = NULL; vp = yasm_vps_first(valparams); @@ -1389,16 +1398,38 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, } if (i == NELEMS(section_name_translation)) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unknown section type, defaulting to .text")); - i = 0; + const char *s; + if (vp && !vp->val && (s = yasm_vp_string(vp))) { + /* Treat as SEGNAME, SECTNAME */ + if (strlen(sectname) > 16) + yasm_warn_set(YASM_WARN_GENERAL, + N_("segment name is too long, max 16 chars; truncating")); + data.f_segname = yasm__xstrndup(sectname, 16); + if (strlen(s) > 16) + yasm_warn_set(YASM_WARN_GENERAL, + N_("section name is too long, max 16 chars; truncating")); + f_sectname = yasm__xstrndup(s, 16); + flags = S_REGULAR; + align = 0; + + sectname = s; + vp = yasm_vps_next(vp); + } else { + data.f_segname = NULL; + if (strlen(sectname) > 16) + yasm_warn_set(YASM_WARN_GENERAL, + N_("section name is too long, max 16 chars; truncating")); + f_sectname = yasm__xstrndup(sectname, 16); + flags = S_ATTR_SOME_INSTRUCTIONS; + align = 0; + } + } else { + data.f_segname = yasm__xstrdup(section_name_translation[i].seg); + f_sectname = yasm__xstrdup(section_name_translation[i].sect); + flags = section_name_translation[i].flags; + align = section_name_translation[i].align; } - f_segname = section_name_translation[i].seg; - f_sectname = section_name_translation[i].sect; - flags = section_name_translation[i].flags; - align = section_name_translation[i].align; - flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help), &data, yasm_dir_helper_valparam_warn); if (flags_override < 0) @@ -1424,8 +1455,19 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, } } - retval = yasm_object_get_general(object, sectname, 0, align, 1, resonly, + if (!data.f_segname) { + yasm_warn_set(YASM_WARN_GENERAL, + N_("Unknown section name, defaulting to __TEXT segment")); + data.f_segname = yasm__xstrdup("__TEXT"); + } + + /* Build a unique sectname from f_segname and f_sectname. */ + realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) + 1 + + strlen(f_sectname) + 1); + sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname); + retval = yasm_object_get_general(object, realname, 0, align, 1, resonly, &isnew, line); + yasm_xfree(realname); if (isnew) msd = macho_objfmt_init_new_section(object, retval, sectname, line); @@ -1434,7 +1476,7 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, if (isnew || yasm_section_is_default(retval)) { yasm_section_set_default(retval, 0); - msd->segname = f_segname; + msd->segname = data.f_segname; msd->sectname = f_sectname; msd->flags = flags; yasm_section_set_align(retval, align, line); @@ -1447,6 +1489,9 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, static void macho_section_data_destroy(void *data) { + macho_section_data *msd = (macho_section_data *) data; + yasm_xfree(msd->segname); + yasm_xfree(msd->sectname); yasm_xfree(data); } diff --git a/modules/objfmts/macho/tests/nasm32/Makefile.inc b/modules/objfmts/macho/tests/nasm32/Makefile.inc index 695208fd..0b3a3c5b 100644 --- a/modules/objfmts/macho/tests/nasm32/Makefile.inc +++ b/modules/objfmts/macho/tests/nasm32/Makefile.inc @@ -8,3 +8,6 @@ EXTRA_DIST += modules/objfmts/macho/tests/nasm32/machotest.asm EXTRA_DIST += modules/objfmts/macho/tests/nasm32/machotest.hex EXTRA_DIST += modules/objfmts/macho/tests/nasm32/macho-reloc.asm EXTRA_DIST += modules/objfmts/macho/tests/nasm32/macho-reloc.hex +EXTRA_DIST += modules/objfmts/macho/tests/nasm32/macho-sect.asm +EXTRA_DIST += modules/objfmts/macho/tests/nasm32/macho-sect.errwarn +EXTRA_DIST += modules/objfmts/macho/tests/nasm32/macho-sect.hex diff --git a/modules/objfmts/macho/tests/nasm32/macho32-sect.asm b/modules/objfmts/macho/tests/nasm32/macho32-sect.asm new file mode 100644 index 00000000..b02f02a4 --- /dev/null +++ b/modules/objfmts/macho/tests/nasm32/macho32-sect.asm @@ -0,0 +1,9 @@ +section .data +section __x +section __y segname=__Y +section __Z, __z +section __Y __bar +section __reallylongname12345 +section __REALLYLONGSEGNAME __1 +section __2 __reallylongsectname +section __2REALLYLONGSEGNAME __2reallylongsectname diff --git a/modules/objfmts/macho/tests/nasm32/macho32-sect.errwarn b/modules/objfmts/macho/tests/nasm32/macho32-sect.errwarn new file mode 100644 index 00000000..620e8782 --- /dev/null +++ b/modules/objfmts/macho/tests/nasm32/macho32-sect.errwarn @@ -0,0 +1,7 @@ +-:2: warning: Unknown section name, defaulting to __TEXT segment +-:6: warning: section name is too long, max 16 chars; truncating +-:6: warning: Unknown section name, defaulting to __TEXT segment +-:7: warning: segment name is too long, max 16 chars; truncating +-:8: warning: section name is too long, max 16 chars; truncating +-:9: warning: segment name is too long, max 16 chars; truncating +-:9: warning: section name is too long, max 16 chars; truncating diff --git a/modules/objfmts/macho/tests/nasm32/macho32-sect.hex b/modules/objfmts/macho/tests/nasm32/macho32-sect.hex new file mode 100644 index 00000000..eff781a5 --- /dev/null +++ b/modules/objfmts/macho/tests/nasm32/macho32-sect.hex @@ -0,0 +1,789 @@ +ce +fa +ed +fe +07 +00 +00 +00 +03 +00 +00 +00 +01 +00 +00 +00 +01 +00 +00 +00 +e0 +02 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +e0 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +fc +02 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +07 +00 +00 +00 +0a +00 +00 +00 +00 +00 +00 +00 +5f +5f +74 +65 +78 +74 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +54 +45 +58 +54 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +80 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +64 +61 +74 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +44 +41 +54 +41 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +78 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +54 +45 +58 +54 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +79 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +59 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +7a +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +5a +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +62 +61 +72 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +59 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +72 +65 +61 +6c +6c +79 +6c +6f +6e +67 +6e +61 +6d +65 +5f +5f +54 +45 +58 +54 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +31 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +52 +45 +41 +4c +4c +59 +4c +4f +4e +47 +53 +45 +47 +4e +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +72 +65 +61 +6c +6c +79 +6c +6f +6e +67 +73 +65 +63 +74 +5f +5f +32 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5f +5f +32 +72 +65 +61 +6c +6c +79 +6c +6f +6e +67 +73 +65 +63 +5f +5f +32 +52 +45 +41 +4c +4c +59 +4c +4f +4e +47 +53 +45 +47 +00 +00 +00 +00 +00 +00 +00 +00 +14 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +18 +00 +00 +00 +fc +02 +00 +00 +00 +00 +00 +00 +fc +02 +00 +00 +01 +00 +00 +00 +00 -- 2.40.0