blob: 3896f78f07ef99e57aeba246125d6821fd7cfc66 [file] [log] [blame]
/* Create descriptor for assembling.
Copyright (C) 2002 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 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 <config.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <gelf.h>
#include "libasmP.h"
#include <system.h>
static AsmCtx_t *
prepare_text_output (AsmCtx_t *result)
{
return result;
}
static AsmCtx_t *
prepare_binary_output (AsmCtx_t *result, int machine, int klass, int data)
{
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. */
if (gelf_newehdr (result->out.elf, klass) == 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 value the user provided. */
ehdr->e_machine = machine;
/* Same for the class and endianness. */
ehdr->e_ident[EI_CLASS] = klass;
ehdr->e_ident[EI_DATA] = data;
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, textp, machine, klass, data)
const char *fname;
bool textp;
int machine;
int klass;
int data;
{
size_t fname_len = strlen (fname);
AsmCtx_t *result;
/* First order of business: find the appropriate backend. If it
does not exist we don't have to look further. */
// XXX
/* 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. */
result = (AsmCtx_t *) malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9);
if (result == NULL)
return NULL;
/* Initialize the lock. */
rwlock_init (result->lock);
/* 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;
}
/* 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, machine, klass, data);
return result;
}