2005-12-08 Wade Tregaskis <wtregaskis@apple.com>
authorEric Christopher <echristo@apple.com>
Fri, 9 Dec 2005 00:27:26 +0000 (00:27 +0000)
committerEric Christopher <echristo@apple.com>
Fri, 9 Dec 2005 00:27:26 +0000 (00:27 +0000)
* nasm/nasm/output/outmacho.c (struct section): Added "align" field.
(sectmap): Added ".rodata" section.
(exact_log2): New.
(macho_section): Added support for section attributes.
        "align=" and "data" specifically.
(macho_write_segment): Write out section alignment to Mach-O file.

output/outmacho.c

index ab5713f..e3603b7 100644 (file)
@@ -52,6 +52,7 @@ struct section {
     struct SAA *data;
     long index;
     struct reloc *relocs;
+    int align;
 
     /* data that goes into the file */
     char sectname[16];          /* what this section is called */
@@ -83,6 +84,7 @@ static struct sectmap {
 } sectmap[] = { {
 ".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS}, {
 ".data", "__DATA", "__data", S_REGULAR}, {
+".rodata", "__DATA", "__const", S_REGULAR}, {
 ".bss", "__DATA", "__bss", S_ZEROFILL}, {
 NULL, NULL, NULL}};
 
@@ -131,6 +133,8 @@ struct symbol {
 
 #define        N_TYPE  0x0e            /* type bit mask */
 
+#define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
+
 /* special section number values */
 #define        NO_SECT         0       /* no section, invalid */
 #define MAX_SECT       255     /* maximum number of sections */
@@ -196,6 +200,24 @@ unsigned long rel_padcnt = 0;
 static void debug_reloc (struct reloc *);
 static void debug_section_relocs (struct section *) __attribute__ ((unused));
 
+static int exact_log2 (unsigned long align) {
+    if (align != (align & -align)) {
+       return -1;
+    } else {
+#ifdef __GNUC__
+       return (align ? __builtin_ctzl (align) : 0);
+#else
+       unsigned long result = 0;
+
+       while (align >>= 1) {
+           ++result;
+       }
+
+       return result;
+#endif
+    }
+}
+
 static struct section *get_section_by_name(const char *segname,
                                            const char *sectname)
 {
@@ -484,22 +506,29 @@ static void macho_output(long secto, const void *data, unsigned long type,
 
 static long macho_section(char *name, int pass, int *bits)
 {
-    long index;
+    long index, originalIndex;
+    char *sectionAttributes;
     struct sectmap *sm;
     struct section *s;
 
     /* Default to 32 bits. */
-    if (!name)
+    if (!name) {
         *bits = 32;
-
-    if (!name)
         name = ".text";
+        sectionAttributes = NULL;
+    } else {
+        sectionAttributes = name;
+        name = strsep(&sectionAttributes, " \t");
+    }
 
     for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
         /* make lookup into section name translation table */
         if (!strcmp(name, sm->nasmsect)) {
+            char *currentAttribute;
+
             /* try to find section with that name */
-            index = get_section_index_by_name(sm->segname, sm->sectname);
+            originalIndex = index = get_section_index_by_name(sm->segname,
+                                                              sm->sectname);
 
             /* create it if it doesn't exist yet */
             if (index == -1) {
@@ -510,6 +539,7 @@ static long macho_section(char *name, int pass, int *bits)
                 s->data = saa_init(1L);
                 s->index = seg_alloc();
                 s->relocs = NULL;
+                s->align = DEFAULT_SECTION_ALIGNMENT;
 
                 xstrncpy(s->segname, sm->segname);
                 xstrncpy(s->sectname, sm->sectname);
@@ -518,6 +548,59 @@ static long macho_section(char *name, int pass, int *bits)
                 s->flags = sm->flags;
 
                 index = s->index;
+            } else {
+                s = get_section_by_index(index);
+            }
+
+            while ((NULL != sectionAttributes)
+                   && (currentAttribute = strsep(&sectionAttributes, " \t"))) {
+                if (0 != *currentAttribute) {
+                    if (0 == strncasecmp("align=", currentAttribute, 6)) {
+                        char *end;
+                        int newAlignment, value;
+
+                        value = strtoul(currentAttribute + 6, &end, 0);
+                        newAlignment = exact_log2(value);
+
+                        if (0 != *end) {
+                            error(ERR_PANIC,
+                                  "unknown or missing alignment value \"%s\" "
+                                      "specified for section \"%s\"",
+                                  currentAttribute + 6,
+                                  name);
+                            return NO_SEG;
+                        } else if (0 > newAlignment) {
+                            error(ERR_PANIC,
+                                  "alignment of %d (for section \"%s\") is not "
+                                      "a power of two",
+                                  value,
+                                  name);
+                            return NO_SEG;
+                        }
+
+                        if ((-1 != originalIndex)
+                            && (s->align != newAlignment)) {
+                            error(ERR_PANIC,
+                                  "section \"%s\" has already been specified "
+                                      "with alignment %d, conflicts with new "
+                                      "alignment of %d",
+                            name,
+                            (1 << s->align),
+                            value);
+                            return NO_SEG;
+                        }
+
+                        s->align = newAlignment;
+                    } else if (0 == strcasecmp("data", currentAttribute)) {
+                        /* Do nothing; 'data' is implicit */
+                    } else {
+                        error(ERR_PANIC,
+                              "unknown section attribute %s for section %s",
+                              currentAttribute,
+                              name);
+                        return NO_SEG;
+                    }
+                }
             }
 
             return index;
@@ -804,7 +887,9 @@ static unsigned long macho_write_segment (unsigned long offset)
        /* dummy data for zerofill sections or proper values */
        if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
            fwritelong(offset, machofp);
-           fwritelong(0, machofp);
+           /* Write out section alignment, as a power of two.
+              e.g. 32-bit word alignment would be 2 (2^^2 = 4).  */
+           fwritelong(s->align, machofp);
            /* To be compatible with cctools as we emit
               a zero reloff if we have no relocations.  */
            fwritelong(s->nreloc ? rel_base + s_reloff : 0, machofp);