| 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 |