* TARGET_ASM_GAS == GNU assembler
*/
#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_ASM_GAS)
-#if defined(__MACH__) && !defined(__native_client_codegen__)
+#if defined(TARGET_MACH) && !defined(__native_client_codegen__)
#define TARGET_ASM_APPLE
#else
#define TARGET_ASM_GAS
/*
* Defines for the directives used by different assemblers
*/
-#if defined(TARGET_POWERPC) || defined(__MACH__)
+#if defined(TARGET_POWERPC) || defined(TARGET_MACH)
#define AS_STRING_DIRECTIVE ".asciz"
#else
#define AS_STRING_DIRECTIVE ".string"
#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
#define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
-#if defined(TARGET_AMD64) && !defined(HOST_WIN32)
+#if defined(TARGET_AMD64) && !defined(HOST_WIN32) && !defined(__APPLE__)
#define USE_ELF_WRITER 1
#define USE_ELF_RELA 1
#endif
-#if defined(TARGET_X86) && !defined(TARGET_WIN32)
+#if defined(TARGET_X86) && !defined(TARGET_WIN32) && !defined(__APPLE__)
#define USE_ELF_WRITER 1
#endif
-#if defined(TARGET_ARM) && !defined(__MACH__)
+#if defined(TARGET_ARM) && !defined(TARGET_MACH)
#define USE_ELF_WRITER 1
#endif
#define USE_ELF_WRITER 1
#endif
-#if defined(USE_ELF_WRITER)
+#if defined(TARGET_X86) && defined(__APPLE__)
+//#define USE_MACH_WRITER
+#endif
+
+#if defined(USE_ELF_WRITER) || defined(USE_MACH_WRITER)
#define USE_BIN_WRITER 1
#endif
{
BinReloc *reloc;
- if (!target)
- // FIXME:
- g_assert_not_reached ();
+ if (!target) {
+ acfg->cur_section->cur_offset += sizeof (gpointer);
+ return;
+ }
+
reloc = g_new0 (BinReloc, 1);
reloc->val1 = g_strdup (target);
reloc->section = acfg->cur_section;
acfg->cur_section->cur_offset += num;
}
+static void
+bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb)
+{
+ if (acfg->fp)
+ fwrite (val, size, nmemb, acfg->fp);
+ else {
+ g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size);
+ memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb);
+ acfg->out_buf_pos += (size * nmemb);
+ }
+}
+
+static void
+bin_writer_fseek (MonoImageWriter *acfg, int offset)
+{
+ if (acfg->fp)
+ fseek (acfg->fp, offset, SEEK_SET);
+ else
+ acfg->out_buf_pos = offset;
+}
+
+#ifdef USE_MACH_WRITER
+
+/*
+ * This is a minimal implementation designed to support xdebug on 32 bit osx
+ * FIXME: 64 bit support
+ */
+
+#include <mach-o/loader.h>
+
+static gsize
+get_label_addr (MonoImageWriter *acfg, const char *name)
+{
+ int offset;
+ BinLabel *lab;
+ BinSection *section;
+ gsize value;
+
+ lab = g_hash_table_lookup (acfg->labels, name);
+ if (!lab)
+ g_error ("Undefined label: '%s'.\n", name);
+ section = lab->section;
+ offset = lab->offset;
+ if (section->parent) {
+ value = section->parent->virt_offset + section->cur_offset + offset;
+ } else {
+ value = section->virt_offset + offset;
+ }
+ return value;
+}
+
+
+static void
+resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val)
+{
+ guint8 *data;
+ gssize end_val, start_val;
+ gsize vaddr;
+
+ end_val = get_label_addr (acfg, reloc->val1);
+ if (reloc->val2) {
+ start_val = get_label_addr (acfg, reloc->val2);
+ } else if (reloc->val2_section) {
+ start_val = reloc->val2_offset;
+ if (reloc->val2_section->parent)
+ start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset;
+ else
+ start_val += reloc->val2_section->virt_offset;
+ } else {
+ start_val = 0;
+ }
+ end_val = end_val - start_val + reloc->offset;
+ if (reloc->section->parent) {
+ data = reloc->section->parent->data;
+ data += reloc->section->cur_offset;
+ data += reloc->section_offset;
+ vaddr = reloc->section->parent->virt_offset;
+ vaddr += reloc->section->cur_offset;
+ vaddr += reloc->section_offset;
+ } else {
+ data = reloc->section->data;
+ data += reloc->section_offset;
+ vaddr = reloc->section->virt_offset;
+ vaddr += reloc->section_offset;
+ }
+
+ *out_start_val = start_val;
+ *out_end_val = end_val;
+ *out_data = data;
+ *out_vaddr = vaddr;
+}
+
+static void
+resolve_relocations (MonoImageWriter *acfg)
+{
+ BinReloc *reloc;
+ guint8 *data;
+ gsize end_val, start_val;
+ gsize vaddr;
+
+ /* Only resolve static relocations */
+ for (reloc = acfg->relocations; reloc; reloc = reloc->next) {
+ resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val);
+ data [0] = end_val;
+ data [1] = end_val >> 8;
+ data [2] = end_val >> 16;
+ data [3] = end_val >> 24;
+ }
+}
+
+static int
+bin_writer_emit_writeout (MonoImageWriter *acfg)
+{
+ BinSection *s;
+ int sindex, file_size, nsections, file_offset, vmaddr;
+ struct mach_header header;
+ struct segment_command segment;
+ struct section *sections;
+
+ /* Assing vm addresses to sections */
+ nsections = 0;
+ vmaddr = 0;
+ for (s = acfg->sections; s; s = s->next) {
+ s->virt_offset = vmaddr;
+ vmaddr += s->cur_offset;
+ nsections ++;
+ }
+
+ resolve_relocations (acfg);
+
+ file_offset = 0;
+
+ memset (&header, 0, sizeof (header));
+ header.magic = MH_MAGIC;
+ header.cputype = CPU_TYPE_X86;
+ header.cpusubtype = CPU_SUBTYPE_X86_ALL;
+ header.filetype = MH_OBJECT;
+ header.ncmds = 0;
+ header.sizeofcmds = 0;
+ header.flags = 0;
+
+ file_offset += sizeof (header);
+
+ memset (&segment, 0, sizeof (segment));
+ segment.cmd = LC_SEGMENT;
+ segment.cmdsize = sizeof (segment);
+ segment.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+ segment.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+
+ file_offset += sizeof (segment);
+ file_offset += nsections * sizeof (struct section);
+
+ sections = g_new0 (struct section, nsections);
+ sindex = 0;
+ for (s = acfg->sections; s; s = s->next) {
+ s->file_offset = file_offset;
+
+ /* .debug_line -> __debug_line */
+ sprintf (sections [sindex].sectname, "__%s", s->name + 1);
+ sprintf (sections [sindex].segname, "%s", "__DWARF");
+ sections [sindex].addr = s->virt_offset;
+ sections [sindex].size = s->cur_offset;
+ sections [sindex].offset = s->file_offset;
+
+ file_offset += s->cur_offset;
+
+ segment.nsects ++;
+ segment.cmdsize += sizeof (struct section);
+
+ sindex ++;
+ }
+
+ header.ncmds ++;
+ header.sizeofcmds += segment.cmdsize;
+
+ /* Emit data */
+ file_size = file_offset;
+
+ if (!acfg->fp) {
+ acfg->out_buf_size = file_size;
+ acfg->out_buf = g_malloc (acfg->out_buf_size);
+ }
+
+ bin_writer_fwrite (acfg, &header, sizeof (header), 1);
+ bin_writer_fwrite (acfg, &segment, sizeof (segment), 1);
+ bin_writer_fwrite (acfg, sections, sizeof (struct section), nsections);
+ for (s = acfg->sections; s; s = s->next) {
+ if (!acfg->fp)
+ g_assert (acfg->out_buf_pos == s->file_offset);
+ bin_writer_fwrite (acfg, s->data, s->cur_offset, 1);
+ }
+
+ if (acfg->fp)
+ fclose (acfg->fp);
+
+ return 0;
+}
+
+#endif
+
#ifdef USE_ELF_WRITER
enum {
#endif /* USE_ELF_RELA */
-static void
-bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb)
-{
- if (acfg->fp)
- fwrite (val, size, nmemb, acfg->fp);
- else {
- g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size);
- memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb);
- acfg->out_buf_pos += (size * nmemb);
- }
-}
-
-static void
-bin_writer_fseek (MonoImageWriter *acfg, int offset)
-{
- if (acfg->fp)
- fseek (acfg->fp, offset, SEEK_SET);
- else
- acfg->out_buf_pos = offset;
-}
-
static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC };
static int
{
FILE *file;
ElfHeader header;
- ElfProgHeader progh [3];
+ ElfProgHeader progh [4];
ElfSectHeader secth [SECT_NUM];
#ifdef USE_ELF_RELA
ElfRelocA *relocs;
header.e_phoff = sizeof (header);
header.e_ehsize = sizeof (header);
header.e_phentsize = sizeof (ElfProgHeader);
- header.e_phnum = 3;
+ header.e_phnum = 4;
header.e_entry = secth [SECT_TEXT].sh_addr;
header.e_shstrndx = SECT_SHSTRTAB;
header.e_shentsize = sizeof (ElfSectHeader);
progh [2].p_align = SIZEOF_VOID_P;
progh [2].p_flags = 6;
+ progh [3].p_type = PT_GNU_STACK;
+ progh [3].p_offset = secth [SECT_DYNAMIC].sh_offset;
+ progh [3].p_vaddr = progh [3].p_paddr = secth [SECT_DYNAMIC].sh_addr;
+ progh [3].p_filesz = progh [3].p_memsz = secth [SECT_DYNAMIC].sh_size;
+ progh [3].p_align = SIZEOF_VOID_P;
+ progh [3].p_flags = 6;
+
/* Compute the addresses of the bin sections, so relocation can be done */
for (i = 0; i < SECT_NUM; ++i) {
if (sections [i]) {
asm_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func)
{
asm_writer_emit_unset_mode (acfg);
-#if (defined(__ppc__) && defined(TARGET_ASM_APPLE)) || (defined(HOST_WIN32) && !defined(MONO_CROSS_COMPILE))
- // mach-o always uses a '_' prefix.
- fprintf (acfg->fp, "\t.globl _%s\n", name);
-#else
+
fprintf (acfg->fp, "\t.globl %s\n", name);
-#endif
asm_writer_emit_symbol_type (acfg, name, func);
}
asm_writer_emit_label (MonoImageWriter *acfg, const char *name)
{
asm_writer_emit_unset_mode (acfg);
-#if defined(HOST_WIN32) && (defined(TARGET_X86) || defined(TARGET_AMD64))
- fprintf (acfg->fp, "_%s:\n", name);
-#if defined(HOST_WIN32)
- /* Emit a normal label too */
- fprintf (acfg->fp, "%s:\n", name);
-#endif
-#else
fprintf (acfg->fp, "%s:\n", get_label (name));
-#endif
-
}
static void
asm_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset)
{
#ifdef TARGET_ASM_APPLE
- char symbol [128];
+ //char symbol [128];
#endif
if (acfg->mode != EMIT_LONG) {
#else
start = get_label (start);
end = get_label (end);
+
+ if (offset == 0 && strcmp (start, ".") != 0) {
+ char symbol [128];
+ sprintf (symbol, "%sDIFF_SYM%d", AS_TEMP_LABEL_PREFIX, acfg->label_gen);
+ acfg->label_gen ++;
+ fprintf (acfg->fp, "\n%s=%s - %s", symbol, end, start);
+ fprintf (acfg->fp, "\n\t%s ", AS_INT32_DIRECTIVE);
+ fprintf (acfg->fp, "%s", symbol);
+ return;
+ }
+
if ((acfg->col_count++ % 8) == 0)
fprintf (acfg->fp, "\n\t%s ", AS_INT32_DIRECTIVE);
else