OLD | NEW |
1 /* | 1 /* |
2 * Mac OS X ABI Mach-O File Format | 2 * Mac OS X ABI Mach-O File Format |
3 * | 3 * |
4 * Copyright (C) 2007 Henryk Richter, built upon xdf objfmt (C) Peter Johnson | 4 * Copyright (C) 2007 Henryk Richter, built upon xdf objfmt (C) Peter Johnson |
5 * | 5 * |
6 * | 6 * |
7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
9 * are met: | 9 * are met: |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 [extern bar] | 84 [extern bar] |
85 section .data | 85 section .data |
86 dq bar-foo | 86 dq bar-foo |
87 | 87 |
88 Will currently produce an error though the necessary means are provided | 88 Will currently produce an error though the necessary means are provided |
89 by the Mach-O specification. | 89 by the Mach-O specification. |
90 | 90 |
91 */ | 91 */ |
92 | 92 |
93 #include <util.h> | 93 #include <util.h> |
94 /*@unused@*/ RCSID("$Id: macho-objfmt.c 2166 2009-01-02 08:33:21Z peter $"); | 94 /*@unused@*/ RCSID("$Id: macho-objfmt.c 2345 2010-08-01 01:27:40Z peter $"); |
95 | 95 |
96 #include <libyasm.h> | 96 #include <libyasm.h> |
97 | 97 |
98 /* MACH-O DEFINES */ | 98 /* MACH-O DEFINES */ |
99 /* Mach-O in-file header structure sizes (32 BIT, see below for 64 bit defs) */ | 99 /* Mach-O in-file header structure sizes (32 BIT, see below for 64 bit defs) */ |
100 #define MACHO_HEADER_SIZE 28 | 100 #define MACHO_HEADER_SIZE 28 |
101 #define MACHO_SEGCMD_SIZE 56 | 101 #define MACHO_SEGCMD_SIZE 56 |
102 #define MACHO_SECTCMD_SIZE 68 | 102 #define MACHO_SECTCMD_SIZE 68 |
103 #define MACHO_SYMCMD_SIZE 24 | 103 #define MACHO_SYMCMD_SIZE 24 |
104 #define MACHO_NLIST_SIZE 12 | 104 #define MACHO_NLIST_SIZE 12 |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 reloc->type = X86_64_RELOC_UNSIGNED; | 525 reloc->type = X86_64_RELOC_UNSIGNED; |
526 } | 526 } |
527 | 527 |
528 /* It seems that x86-64 objects need to have all extern relocs? */ | 528 /* It seems that x86-64 objects need to have all extern relocs? */ |
529 if (info->is_64) | 529 if (info->is_64) |
530 reloc->ext = 1; | 530 reloc->ext = 1; |
531 | 531 |
532 if ((vis & YASM_SYM_EXTERN) || (vis & YASM_SYM_COMMON)) { | 532 if ((vis & YASM_SYM_EXTERN) || (vis & YASM_SYM_COMMON)) { |
533 reloc->ext = 1; | 533 reloc->ext = 1; |
534 info->msd->extreloc = 1; /* section has external relocations */ | 534 info->msd->extreloc = 1; /* section has external relocations */ |
535 } else if (!value->curpos_rel && !info->is_64) { | 535 } else if (!info->is_64) { |
536 /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc; | 536 /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc; |
537 | 537 |
538 /* Local symbols need valued to their actual address */ | 538 /* Local symbols need valued to their actual address */ |
539 if (yasm_symrec_get_label(value->rel, &sym_precbc)) { | 539 if (yasm_symrec_get_label(value->rel, &sym_precbc)) { |
540 yasm_section *sym_sect = yasm_bc_get_section(sym_precbc); | 540 yasm_section *sym_sect = yasm_bc_get_section(sym_precbc); |
541 /*@null@*/ macho_section_data *msd; | 541 /*@null@*/ macho_section_data *msd; |
542 msd = yasm_section_get_data(sym_sect, &macho_section_data_cb); | 542 msd = yasm_section_get_data(sym_sect, &macho_section_data_cb); |
543 assert(msd != NULL); | 543 assert(msd != NULL); |
544 intn_plus += msd->vmoff + yasm_bc_next_offset(sym_precbc); | 544 intn_plus += msd->vmoff + yasm_bc_next_offset(sym_precbc); |
545 } | 545 } |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 /* accumulate size in memory */ | 994 /* accumulate size in memory */ |
995 msd->vmoff = info->vmsize; | 995 msd->vmoff = info->vmsize; |
996 info->vmsize += msd->size; | 996 info->vmsize += msd->size; |
997 | 997 |
998 /* align both start and end of section */ | 998 /* align both start and end of section */ |
999 align = yasm_section_get_align(sect); | 999 align = yasm_section_get_align(sect); |
1000 if (align != 0) { | 1000 if (align != 0) { |
1001 unsigned long delta = msd->vmoff % align; | 1001 unsigned long delta = msd->vmoff % align; |
1002 if (delta > 0) { | 1002 if (delta > 0) { |
1003 msd->vmoff += align - delta; | 1003 msd->vmoff += align - delta; |
1004 info->vmsize += delta; | 1004 info->vmsize += align - delta; |
1005 } | 1005 } |
1006 } | 1006 } |
1007 | 1007 |
1008 return 0; | 1008 return 0; |
1009 } | 1009 } |
1010 | 1010 |
1011 /* write object */ | 1011 /* write object */ |
1012 static void | 1012 static void |
1013 macho_objfmt_output(yasm_object *object, FILE *f, int all_syms, | 1013 macho_objfmt_output(yasm_object *object, FILE *f, int all_syms, |
1014 yasm_errwarns *errwarns) | 1014 yasm_errwarns *errwarns) |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1181 YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, initial */ | 1181 YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, initial */ |
1182 /* number of sections */ | 1182 /* number of sections */ |
1183 YASM_WRITE_32_L(localbuf, objfmt_macho->parse_scnum); | 1183 YASM_WRITE_32_L(localbuf, objfmt_macho->parse_scnum); |
1184 YASM_WRITE_32_L(localbuf, 0); /* no flags */ | 1184 YASM_WRITE_32_L(localbuf, 0); /* no flags */ |
1185 | 1185 |
1186 /* write MACH-O header and segment command to outfile */ | 1186 /* write MACH-O header and segment command to outfile */ |
1187 fwrite(info.buf, (size_t) (localbuf - info.buf), 1, f); | 1187 fwrite(info.buf, (size_t) (localbuf - info.buf), 1, f); |
1188 | 1188 |
1189 /* next: section headers */ | 1189 /* next: section headers */ |
1190 /* offset to relocs for first section */ | 1190 /* offset to relocs for first section */ |
1191 info.rel_base = align32((long)fileoffset + (long)info.filesize); | 1191 info.rel_base = align32((long)fileoff_sections); |
1192 info.s_reloff = 0; /* offset for relocs of following sections */ | 1192 info.s_reloff = 0; /* offset for relocs of following sections */ |
1193 yasm_object_sections_traverse(object, &info, macho_objfmt_output_secthead); | 1193 yasm_object_sections_traverse(object, &info, macho_objfmt_output_secthead); |
1194 | 1194 |
1195 localbuf = info.buf; | 1195 localbuf = info.buf; |
1196 /* write out symbol command */ | 1196 /* write out symbol command */ |
1197 YASM_WRITE_32_L(localbuf, LC_SYMTAB); /* cmd == LC_SYMTAB */ | 1197 YASM_WRITE_32_L(localbuf, LC_SYMTAB); /* cmd == LC_SYMTAB */ |
1198 YASM_WRITE_32_L(localbuf, MACHO_SYMCMD_SIZE); | 1198 YASM_WRITE_32_L(localbuf, MACHO_SYMCMD_SIZE); |
1199 /* symbol table offset */ | 1199 /* symbol table offset */ |
1200 YASM_WRITE_32_L(localbuf, info.rel_base + info.s_reloff); | 1200 YASM_WRITE_32_L(localbuf, info.rel_base + info.s_reloff); |
1201 YASM_WRITE_32_L(localbuf, symtab_count); /* number of symbols */ | 1201 YASM_WRITE_32_L(localbuf, symtab_count); /* number of symbols */ |
1202 | 1202 |
1203 YASM_WRITE_32_L(localbuf, macho_nlistsize * symtab_count + info.rel_base + | 1203 YASM_WRITE_32_L(localbuf, macho_nlistsize * symtab_count + info.rel_base + |
1204 info.s_reloff); /* string table offset */ | 1204 info.s_reloff); /* string table offset */ |
1205 YASM_WRITE_32_L(localbuf, info.strlength); /* string table size */ | 1205 YASM_WRITE_32_L(localbuf, info.strlength); /* string table size */ |
1206 /* write symbol command */ | 1206 /* write symbol command */ |
1207 fwrite(info.buf, (size_t)(localbuf - info.buf), 1, f); | 1207 fwrite(info.buf, (size_t)(localbuf - info.buf), 1, f); |
1208 | 1208 |
1209 /*printf("num symbols %d, vmsize %d, filesize %d\n",symtab_count, | 1209 /*printf("num symbols %d, vmsize %d, filesize %d\n",symtab_count, |
1210 info.vmsize, info.filesize ); */ | 1210 info.vmsize, info.filesize ); */ |
1211 | 1211 |
1212 /* get back to end of raw section data */ | 1212 /* get back to end of raw section data */ |
1213 if (fseek(f, (long)fileoff_sections, SEEK_SET) < 0) { | 1213 if (fseek(f, (long)fileoff_sections, SEEK_SET) < 0) { |
1214 yasm__fatal(N_("could not seek on output file")); | 1214 yasm__fatal(N_("could not seek on output file")); |
1215 /*@notreached@*/ | 1215 /*@notreached@*/ |
1216 return; | 1216 return; |
1217 } | 1217 } |
1218 | 1218 |
1219 /* padding to long boundary */ | 1219 /* padding to long boundary */ |
1220 if (info.rel_base - (fileoffset + info.filesize)) { | 1220 if ((info.rel_base - fileoff_sections) > 0) { |
1221 fwrite(pad_data, info.rel_base - (fileoffset + info.filesize), 1, f); | 1221 fwrite(pad_data, info.rel_base - fileoff_sections, 1, f); |
1222 } | 1222 } |
1223 | 1223 |
1224 /* relocation data */ | 1224 /* relocation data */ |
1225 yasm_object_sections_traverse(object, &info, macho_objfmt_output_relocs); | 1225 yasm_object_sections_traverse(object, &info, macho_objfmt_output_relocs); |
1226 | 1226 |
1227 /* symbol table (NLIST) */ | 1227 /* symbol table (NLIST) */ |
1228 info.indx = 1; /* restart symbol table indices */ | 1228 info.indx = 1; /* restart symbol table indices */ |
1229 yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_symtable); | 1229 yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_symtable); |
1230 | 1230 |
1231 /* symbol strings */ | 1231 /* symbol strings */ |
1232 fwrite(pad_data, 1, 1, f); | 1232 fwrite(pad_data, 1, 1, f); |
1233 yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_str); | 1233 yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_str); |
1234 | 1234 |
1235 yasm_intnum_destroy(val); | 1235 yasm_intnum_destroy(val); |
1236 yasm_xfree(info.buf); | 1236 yasm_xfree(info.buf); |
1237 } | 1237 } |
1238 | 1238 |
1239 static void | 1239 static void |
1240 macho_objfmt_destroy(yasm_objfmt *objfmt) | 1240 macho_objfmt_destroy(yasm_objfmt *objfmt) |
1241 { | 1241 { |
1242 yasm_xfree(objfmt); | 1242 yasm_xfree(objfmt); |
1243 } | 1243 } |
1244 | 1244 |
1245 static macho_section_data * | 1245 static void |
1246 macho_objfmt_init_new_section(yasm_object *object, yasm_section *sect, | 1246 macho_objfmt_init_new_section(yasm_section *sect, unsigned long line) |
1247 const char *sectname, unsigned long line) | |
1248 { | 1247 { |
| 1248 yasm_object *object = yasm_section_get_object(sect); |
| 1249 const char *sectname = yasm_section_get_name(sect); |
1249 yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt; | 1250 yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt; |
1250 macho_section_data *data; | 1251 macho_section_data *data; |
1251 yasm_symrec *sym; | 1252 yasm_symrec *sym; |
1252 | 1253 |
1253 data = yasm_xmalloc(sizeof(macho_section_data)); | 1254 data = yasm_xmalloc(sizeof(macho_section_data)); |
1254 data->scnum = objfmt_macho->parse_scnum++; | 1255 data->scnum = objfmt_macho->parse_scnum++; |
1255 data->segname = NULL; | 1256 data->segname = NULL; |
1256 data->sectname = NULL; | 1257 data->sectname = NULL; |
1257 data->flags = S_REGULAR; | 1258 data->flags = S_REGULAR; |
1258 data->size = 0; | 1259 data->size = 0; |
1259 data->offset = 0; | 1260 data->offset = 0; |
1260 data->vmoff = 0; | 1261 data->vmoff = 0; |
1261 data->nreloc = 0; | 1262 data->nreloc = 0; |
1262 data->extreloc = 0; | 1263 data->extreloc = 0; |
1263 yasm_section_add_data(sect, &macho_section_data_cb, data); | 1264 yasm_section_add_data(sect, &macho_section_data_cb, data); |
1264 | 1265 |
1265 sym = yasm_symtab_define_label(object->symtab, sectname, | 1266 sym = yasm_symtab_define_label(object->symtab, sectname, |
1266 yasm_section_bcs_first(sect), 1, line); | 1267 yasm_section_bcs_first(sect), 1, line); |
1267 data->sym = sym; | 1268 data->sym = sym; |
1268 return data; | |
1269 } | 1269 } |
1270 | 1270 |
1271 static yasm_section * | 1271 static yasm_section * |
1272 macho_objfmt_add_default_section(yasm_object *object) | 1272 macho_objfmt_add_default_section(yasm_object *object) |
1273 { | 1273 { |
1274 yasm_section *retval; | 1274 yasm_section *retval; |
1275 macho_section_data *msd; | 1275 macho_section_data *msd; |
1276 int isnew; | 1276 int isnew; |
1277 | 1277 |
1278 retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 1, | 1278 retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 1, |
1279 0, &isnew, 0); | 1279 0, &isnew, 0); |
1280 if (isnew) { | 1280 if (isnew) { |
1281 msd = macho_objfmt_init_new_section(object, retval, ".text", 0); | 1281 msd = yasm_section_get_data(retval, &macho_section_data_cb); |
1282 msd->segname = yasm__xstrdup("__TEXT"); | 1282 msd->segname = yasm__xstrdup("__TEXT"); |
1283 msd->sectname = yasm__xstrdup("__text"); | 1283 msd->sectname = yasm__xstrdup("__text"); |
1284 msd->flags = S_ATTR_PURE_INSTRUCTIONS; | 1284 msd->flags = S_ATTR_PURE_INSTRUCTIONS; |
1285 yasm_section_set_align(retval, 0, 0); | 1285 yasm_section_set_align(retval, 0, 0); |
1286 yasm_section_set_default(retval, 1); | 1286 yasm_section_set_default(retval, 1); |
1287 } | 1287 } |
1288 return retval; | 1288 return retval; |
1289 } | 1289 } |
1290 | 1290 |
1291 static /*@observer@*/ /*@null@*/ yasm_section * | 1291 static /*@observer@*/ /*@null@*/ yasm_section * |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 } | 1464 } |
1465 | 1465 |
1466 /* Build a unique sectname from f_segname and f_sectname. */ | 1466 /* Build a unique sectname from f_segname and f_sectname. */ |
1467 realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) +
1 + | 1467 realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) +
1 + |
1468 strlen(f_sectname) + 1); | 1468 strlen(f_sectname) + 1); |
1469 sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname); | 1469 sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname); |
1470 retval = yasm_object_get_general(object, realname, align, 1, resonly, | 1470 retval = yasm_object_get_general(object, realname, align, 1, resonly, |
1471 &isnew, line); | 1471 &isnew, line); |
1472 yasm_xfree(realname); | 1472 yasm_xfree(realname); |
1473 | 1473 |
1474 if (isnew) | 1474 msd = yasm_section_get_data(retval, &macho_section_data_cb); |
1475 msd = macho_objfmt_init_new_section(object, retval, sectname, line); | |
1476 else | |
1477 msd = yasm_section_get_data(retval, &macho_section_data_cb); | |
1478 | 1475 |
1479 if (isnew || yasm_section_is_default(retval)) { | 1476 if (isnew || yasm_section_is_default(retval)) { |
1480 yasm_section_set_default(retval, 0); | 1477 yasm_section_set_default(retval, 0); |
1481 msd->segname = data.f_segname; | 1478 msd->segname = data.f_segname; |
1482 msd->sectname = f_sectname; | 1479 msd->sectname = f_sectname; |
1483 msd->flags = flags; | 1480 msd->flags = flags; |
1484 yasm_section_set_align(retval, align, line); | 1481 yasm_section_set_align(retval, align, line); |
1485 } else if (flags_override) | 1482 } else if (flags_override) |
1486 yasm_warn_set(YASM_WARN_GENERAL, | 1483 yasm_warn_set(YASM_WARN_GENERAL, |
1487 N_("section flags ignored on section redeclaration")); | 1484 N_("section flags ignored on section redeclaration")); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 32, | 1554 32, |
1558 0, | 1555 0, |
1559 macho_objfmt_dbgfmt_keywords, | 1556 macho_objfmt_dbgfmt_keywords, |
1560 "null", | 1557 "null", |
1561 NULL, /* no directives */ | 1558 NULL, /* no directives */ |
1562 NULL, /* no standard macros */ | 1559 NULL, /* no standard macros */ |
1563 macho_objfmt_create, | 1560 macho_objfmt_create, |
1564 macho_objfmt_output, | 1561 macho_objfmt_output, |
1565 macho_objfmt_destroy, | 1562 macho_objfmt_destroy, |
1566 macho_objfmt_add_default_section, | 1563 macho_objfmt_add_default_section, |
| 1564 macho_objfmt_init_new_section, |
1567 macho_objfmt_section_switch, | 1565 macho_objfmt_section_switch, |
1568 macho_objfmt_get_special_sym | 1566 macho_objfmt_get_special_sym |
1569 }; | 1567 }; |
1570 | 1568 |
1571 yasm_objfmt_module yasm_macho32_LTX_objfmt = { | 1569 yasm_objfmt_module yasm_macho32_LTX_objfmt = { |
1572 "Mac OS X ABI Mach-O File Format (32-bit)", | 1570 "Mac OS X ABI Mach-O File Format (32-bit)", |
1573 "macho32", | 1571 "macho32", |
1574 "o", | 1572 "o", |
1575 32, | 1573 32, |
1576 0, | 1574 0, |
1577 macho_objfmt_dbgfmt_keywords, | 1575 macho_objfmt_dbgfmt_keywords, |
1578 "null", | 1576 "null", |
1579 NULL, /* no directives */ | 1577 NULL, /* no directives */ |
1580 NULL, /* no standard macros */ | 1578 NULL, /* no standard macros */ |
1581 macho32_objfmt_create, | 1579 macho32_objfmt_create, |
1582 macho_objfmt_output, | 1580 macho_objfmt_output, |
1583 macho_objfmt_destroy, | 1581 macho_objfmt_destroy, |
1584 macho_objfmt_add_default_section, | 1582 macho_objfmt_add_default_section, |
| 1583 macho_objfmt_init_new_section, |
1585 macho_objfmt_section_switch, | 1584 macho_objfmt_section_switch, |
1586 macho_objfmt_get_special_sym | 1585 macho_objfmt_get_special_sym |
1587 }; | 1586 }; |
1588 | 1587 |
1589 yasm_objfmt_module yasm_macho64_LTX_objfmt = { | 1588 yasm_objfmt_module yasm_macho64_LTX_objfmt = { |
1590 "Mac OS X ABI Mach-O File Format (64-bit)", | 1589 "Mac OS X ABI Mach-O File Format (64-bit)", |
1591 "macho64", | 1590 "macho64", |
1592 "o", | 1591 "o", |
1593 64, | 1592 64, |
1594 0, | 1593 0, |
1595 macho_objfmt_dbgfmt_keywords, | 1594 macho_objfmt_dbgfmt_keywords, |
1596 "null", | 1595 "null", |
1597 NULL, /* no directives */ | 1596 NULL, /* no directives */ |
1598 NULL, /* no standard macros */ | 1597 NULL, /* no standard macros */ |
1599 macho64_objfmt_create, | 1598 macho64_objfmt_create, |
1600 macho_objfmt_output, | 1599 macho_objfmt_output, |
1601 macho_objfmt_destroy, | 1600 macho_objfmt_destroy, |
1602 macho_objfmt_add_default_section, | 1601 macho_objfmt_add_default_section, |
| 1602 macho_objfmt_init_new_section, |
1603 macho_objfmt_section_switch, | 1603 macho_objfmt_section_switch, |
1604 macho_objfmt_get_special_sym | 1604 macho_objfmt_get_special_sym |
1605 }; | 1605 }; |
OLD | NEW |