/* Create descriptor for assembling. Copyright (C) 2002 Red Hat, Inc. Written by Ulrich Drepper , 2002. This program is Open Source software; you can redistribute it and/or modify it under the terms of the Open Software License version 1.0 as published by the Open Source Initiative. You should have received a copy of the Open Software License along with this program; if not, you may obtain a copy of the Open Software License version 1.0 from http://www.opensource.org/licenses/osl.php or by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 3001 King Ranch Road, Ukiah, CA 95482. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include "libasmP.h" #include static AsmCtx_t * prepare_text_output (AsmCtx_t *result) { if (result->fd == -1) result->out.file = stdout; else { result->out.file = fdopen (result->fd, "a"); if (result->out.file == NULL) { close (result->fd); free (result); result = NULL; } __fsetlocking (result->out.file, FSETLOCKING_BYCALLER); } return result; } static AsmCtx_t * prepare_binary_output (AsmCtx_t *result, Ebl *ebl) { GElf_Ehdr *ehdr; GElf_Ehdr ehdr_mem; /* Create the ELF descriptor for the file. */ result->out.elf = elf_begin (result->fd, ELF_C_WRITE_MMAP, NULL); if (result->out.elf == NULL) { err_libelf: unlink (result->tmp_fname); close (result->fd); free (result); __libasm_seterrno (ASM_E_LIBELF); return NULL; } /* Create the ELF header for the output file. */ int class = ebl_get_elfclass (ebl); if (gelf_newehdr (result->out.elf, class) == 0) goto err_libelf; ehdr = gelf_getehdr (result->out.elf, &ehdr_mem); /* If this failed we are in trouble. */ assert (ehdr != NULL); /* We create an object file. */ ehdr->e_type = ET_REL; /* Set the ELF version. */ ehdr->e_version = EV_CURRENT; /* Use the machine, class, and endianess values from the Ebl descriptor. */ ehdr->e_machine = ebl_get_elfmachine (ebl); ehdr->e_ident[EI_CLASS] = class; ehdr->e_ident[EI_DATA] = ebl_get_elfdata (ebl); memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG); /* Write the ELF header information back. */ (void) gelf_update_ehdr (result->out.elf, ehdr); /* No section so far. */ result->section_list = NULL; /* Initialize the hash table. */ asm_symbol_tab_init (&result->symbol_tab, 67); result->nsymbol_tab = 0; /* And the string tables. */ result->section_strtab = ebl_strtabinit (true); result->symbol_strtab = ebl_strtabinit (true); /* We have no section groups so far. */ result->groups = NULL; result->ngroups = 0; return result; } AsmCtx_t * asm_begin (fname, ebl, textp) const char *fname; Ebl *ebl; bool textp; { if (fname == NULL && ! textp) return NULL; size_t fname_len = fname != NULL ? strlen (fname) : 0; /* Create the file descriptor. We do not generate the output file right away. Instead we create a temporary file in the same directory which, if everything goes alright, will replace a possibly existing file with the given name. */ AsmCtx_t *result = (AsmCtx_t *) malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9); if (result == NULL) return NULL; /* Initialize the lock. */ rwlock_init (result->lock); if (fname != NULL) { /* Create the name of the temporary file. */ result->fname = stpcpy (mempcpy (result->tmp_fname, fname, fname_len), ".XXXXXX") + 1; memcpy (result->fname, fname, fname_len + 1); /* Create the temporary file. */ result->fd = mkstemp (result->tmp_fname); if (result->fd == -1) { int save_errno = errno; free (result); __libasm_seterrno (ASM_E_CANNOT_CREATE); errno = save_errno; return NULL; } } else result->fd = -1; /* Initialize the counter for temporary symbols. */ result->tempsym_count = 0; /* Now we differentiate between textual and binary output. */ result->textp = textp; if (textp) result = prepare_text_output (result); else result = prepare_binary_output (result, ebl); return result; }