summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Darbois <mayeut@users.noreply.github.com>2018-02-25 17:40:25 +0300
committerCyrill Gorcunov <gorcunov@gmail.com>2018-02-25 17:41:54 +0300
commit9adfd34b03b9c721bca3b6814c3c1549d82364fc (patch)
tree7119e0093332261b9d4cde977cedc7d00608af82
parent8a7c6009fbddd7084fdfaebd9e3e3fd0baa39bc2 (diff)
downloadnasm-9adfd34b03b9c721bca3b6814c3c1549d82364fc.tar.gz
output: macho -- Add support for N_PEXT in macho output
This allows to mark global symbols as private external. Similar to visibility hidden in ELF output. Signed-off-by: Matthieu Darbois <mayeut@users.noreply.github.com> Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
-rw-r--r--output/outmacho.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/output/outmacho.c b/output/outmacho.c
index 9d55269d..266a3dd1 100644
--- a/output/outmacho.c
+++ b/output/outmacho.c
@@ -233,6 +233,7 @@ struct symbol {
/* symbol type bits */
#define N_EXT 0x01 /* global or external symbol */
+#define N_PEXT 0x10 /* private external symbol */
#define N_UNDF 0x0 /* undefined symbol | n_sect == */
#define N_ABS 0x2 /* absolute symbol | NO_SECT */
@@ -992,14 +993,29 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
{
struct symbol *sym;
struct section *s;
+ bool special_used = false;
- if (special) {
- nasm_error(ERR_NONFATAL, "The Mach-O output format does "
- "not support any special symbol types");
- return;
- }
+#if defined(DEBUG) && DEBUG>2
+ nasm_error(ERR_DEBUG,
+ " macho_symdef: %s, sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
+ name, section, offset, is_global, special);
+#endif
if (is_global == 3) {
+ if (special) {
+ int n = strcspn(special, " \t");
+
+ if (!nasm_strnicmp(special, "private_extern", n)) {
+ for (sym = syms; sym != NULL; sym = sym->next) {
+ if (!strcmp(name, sym->name)) {
+ if (sym->type & N_PEXT)
+ return; /* nothing to be done */
+ else
+ break;
+ }
+ }
+ }
+ }
nasm_error(ERR_NONFATAL, "The Mach-O format does not "
"(yet) support forward reference fixups.");
return;
@@ -1032,6 +1048,18 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
if (is_global != 0) {
sym->type |= N_EXT;
}
+ if (is_global == 1) {
+ /* check special to see if the global symbol shall be marked as private external: N_PEXT */
+ if (special) {
+ int n = strcspn(special, " \t");
+
+ if (!nasm_strnicmp(special, "private_extern", n))
+ sym->type |= N_PEXT;
+ else
+ nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special);
+ }
+ special_used = true;
+ }
if (section == NO_SEG) {
/* symbols in no section get absolute */
@@ -1083,6 +1111,9 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
}
++nsyms;
+
+ if (special && !special_used)
+ nasm_error(ERR_NONFATAL, "no special symbol features supported here");
}
static void macho_sectalign(int32_t seg, unsigned int value)