1 /* Create descriptor for assembling. 2 Copyright (C) 2002 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 2002. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15 #ifdef HAVE_CONFIG_H 16 # include <config.h> 17 #endif 18 19 #include <assert.h> 20 #include <errno.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include <gelf.h> 26 #include "libasmP.h" 27 #include <system.h> 28 29 30 static AsmCtx_t * 31 prepare_text_output (AsmCtx_t *result) 32 { 33 return result; 34 } 35 36 37 static AsmCtx_t * 38 prepare_binary_output (AsmCtx_t *result, int machine, int klass, int data) 39 { 40 GElf_Ehdr *ehdr; 41 GElf_Ehdr ehdr_mem; 42 43 /* Create the ELF descriptor for the file. */ 44 result->out.elf = elf_begin (result->fd, ELF_C_WRITE_MMAP, NULL); 45 if (result->out.elf == NULL) 46 { 47 err_libelf: 48 unlink (result->tmp_fname); 49 close (result->fd); 50 free (result); 51 __libasm_seterrno (ASM_E_LIBELF); 52 return NULL; 53 } 54 55 /* Create the ELF header for the output file. */ 56 if (gelf_newehdr (result->out.elf, klass) == 0) 57 goto err_libelf; 58 59 ehdr = gelf_getehdr (result->out.elf, &ehdr_mem); 60 /* If this failed we are in trouble. */ 61 assert (ehdr != NULL); 62 63 /* We create an object file. */ 64 ehdr->e_type = ET_REL; 65 /* Set the ELF version. */ 66 ehdr->e_version = EV_CURRENT; 67 68 /* Use the machine value the user provided. */ 69 ehdr->e_machine = machine; 70 /* Same for the class and endianness. */ 71 ehdr->e_ident[EI_CLASS] = klass; 72 ehdr->e_ident[EI_DATA] = data; 73 74 memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG); 75 76 /* Write the ELF header information back. */ 77 (void) gelf_update_ehdr (result->out.elf, ehdr); 78 79 /* No section so far. */ 80 result->section_list = NULL; 81 82 /* Initialize the hash table. */ 83 asm_symbol_tab_init (&result->symbol_tab, 67); 84 result->nsymbol_tab = 0; 85 /* And the string tables. */ 86 result->section_strtab = ebl_strtabinit (true); 87 result->symbol_strtab = ebl_strtabinit (true); 88 89 /* We have no section groups so far. */ 90 result->groups = NULL; 91 result->ngroups = 0; 92 93 return result; 94 } 95 96 97 AsmCtx_t * 98 asm_begin (fname, textp, machine, klass, data) 99 const char *fname; 100 bool textp; 101 int machine; 102 int klass; 103 int data; 104 { 105 size_t fname_len = strlen (fname); 106 AsmCtx_t *result; 107 108 109 /* First order of business: find the appropriate backend. If it 110 does not exist we don't have to look further. */ 111 // XXX 112 113 /* Create the file descriptor. We do not generate the output file 114 right away. Instead we create a temporary file in the same 115 directory which, if everything goes alright, will replace a 116 possibly existing file with the given name. */ 117 result = (AsmCtx_t *) malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9); 118 if (result == NULL) 119 return NULL; 120 121 /* Initialize the lock. */ 122 rwlock_init (result->lock); 123 124 /* Create the name of the temporary file. */ 125 result->fname = stpcpy (mempcpy (result->tmp_fname, fname, fname_len), 126 ".XXXXXX") + 1; 127 memcpy (result->fname, fname, fname_len + 1); 128 129 /* Create the temporary file. */ 130 result->fd = mkstemp (result->tmp_fname); 131 if (result->fd == -1) 132 { 133 int save_errno = errno; 134 free (result); 135 __libasm_seterrno (ASM_E_CANNOT_CREATE); 136 errno = save_errno; 137 return NULL; 138 } 139 140 /* Initialize the counter for temporary symbols. */ 141 result->tempsym_count = 0; 142 143 /* Now we differentiate between textual and binary output. */ 144 result->textp = textp; 145 if (textp) 146 result = prepare_text_output (result); 147 else 148 result = prepare_binary_output (result, machine, klass, data); 149 150 return result; 151 } 152