diff options
Diffstat (limited to 'libasm')
38 files changed, 4664 insertions, 0 deletions
diff --git a/libasm/ChangeLog b/libasm/ChangeLog new file mode 100644 index 0000000..f9a863d --- /dev/null +++ b/libasm/ChangeLog @@ -0,0 +1,125 @@ +2011-02-08 Roland McGrath <roland@redhat.com> + + * asm_newscn.c (asm_newscn): Remove unused variable. + +2010-02-15 Roland McGrath <roland@redhat.com> + + * Makefile.am: Use config/eu.am for common stuff. + +2009-01-10 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Use USE_LOCKS instead of USE_TLS. + * asm_error.c: Always use __thread. Remove all !USE_TLS code. + +2008-12-03 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am [USE_TLS]: Like libasm.so with libpthread. + +2008-01-11 Ulrich Drepper <drepper@redhat.com> + + * libasm.h (DisasmGetSymCB_t): Change type of fourth and fifth + parameter. + * disasm_cb.c: Adjust accordingly. + +2008-01-08 Roland McGrath <roland@redhat.com> + + * Makefile.am (euinclude): Variable removed. + (pkginclude_HEADERS): Set this instead of euinclude_HEADERS. + +2007-12-20 Ulrich Drepper <drepper@redhat.com> + + * disasm_cb.c: Add initial support to resolve addresses to symbols. + +2007-02-05 Ulrich Drepper <drepper@redhat.com> + + * disasm_begin.c: New file. + * disasm_cb.c: New file. + * disasm_end.c: New file. + * disasm_str.c: New file. + +2006-08-29 Roland McGrath <roland@redhat.com> + + * Makefile.am (CLEANFILES): Add libasm.so.$(VERSION). + +2005-11-13 Roland McGrath <roland@redhat.com> + + * Makefile.am (INCLUDES): Search in libdw. + +2005-09-02 Ulrich Drepper <drepper@redhat.com> + + * asm_error.c (asm_errmsg): Unify error message. + +2005-08-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Use $(LINK) not $(CC) when creating DSO. + (%.os): Use COMPILE.os. + (COMPILE.os): Filter out gconv options. + +2005-08-02 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (AM_CFLAGS): Add -std=gnu99. + * asm_abort.c: Don't try to remove output file if there is none. + * asm_addint8.c: In print mode, print to file not stdout. + * asm_addsleb128.c: Likewise. + * asm_adduleb128.c: Likewise. + * asm_newscn.c: Likewise. + * asm_align.c: Implement print mode. + * asm_begin.c (asm_begin): Change interface. Take binary class and + byte order information from new Ebl parameter. + * libasm.h: Adjust prototype. + * asm_end.c (text_end): Close file if necesary. + * asm_error.c: Add new error ASM_E_IOERROR. + * libasmP.h: Add ASM_E_IOERROR definition. + +2005-02-15 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2. + + * asm_end.c (text_end): Mark parameter as possibly unused. + +2005-02-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Remove lint handling. + +2005-02-05 Ulrich Drepper <drepper@redhat.com> + + * asm_end.c (binary_end): Don't terminate with error() in case + something goes wrong. + + * Makefile.am: Check for text relocations in constructed DSO. + + * Makefile.am (AM_CFLAGS): More warnings. Add -fmudflap for MUDFLAP. + + * asm_end.c (binary_end): Remove shadowing variables. + Little cleanups. + + * asm_newsym.c: Allocate memory for the string parameter. + +2005-02-04 Ulrich Drepper <drepper@redhat.com> + + * asm_newscn_ingrp.c (asm_newscn_ingrp): Use INTUSE to reference + asm_newscn. + +2004-09-25 Ulrich Drepper <drepper@redhat.com> + + * asm_error.c: Make compile with gcc 4.0. + +2004-01-20 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Support building with mudflap. + +2004-01-18 Ulrich Drepper <drepper@redhat.com> + + * libasmP.h (_): Use elfutils domain. + +2004-01-17 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Support building with mudflap. + +2003-08-13 Ulrich Drepper <drepper@redhat.com> + + * Makefile.in: Depend on libebl.a, not libebl.so. + +2003-08-11 Ulrich Drepper <drepper@redhat.com> + + * Moved to CVS archive. diff --git a/libasm/Makefile.am b/libasm/Makefile.am new file mode 100644 index 0000000..52de7a3 --- /dev/null +++ b/libasm/Makefile.am @@ -0,0 +1,88 @@ +## Process this file with automake to create Makefile.in +## +## Copyright (C) 2002-2010 Red Hat, Inc. +## This file is part of Red Hat elfutils. +## +## Red Hat elfutils is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by the +## Free Software Foundation; version 2 of the License. +## +## Red Hat elfutils is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with Red Hat elfutils; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +## +## Red Hat elfutils is an included package of the Open Invention Network. +## An included package of the Open Invention Network is a package for which +## Open Invention Network licensees cross-license their patents. No patent +## license is granted, either expressly or impliedly, by designation as an +## included package. Should you wish to participate in the Open Invention +## Network licensing program, please visit www.openinventionnetwork.com +## <http://www.openinventionnetwork.com>. +## +include $(top_srcdir)/config/eu.am +INCLUDES += -I$(top_srcdir)/libelf -I$(top_srcdir)/libebl -I$(top_srcdir)/libdw + +GCC_INCLUDE = -I$(shell $(CC) -print-file-name=include) +VERSION = 1 + +lib_LIBRARIES = libasm.a +if !MUDFLAP +noinst_LIBRARIES = libasm_pic.a +noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so) +endif +pkginclude_HEADERS = libasm.h + +libasm_a_SOURCES = asm_begin.c asm_abort.c asm_end.c asm_error.c \ + asm_getelf.c asm_newscn.c asm_newscn_ingrp.c \ + asm_newsubscn.c asm_newsym.c asm_newcomsym.c \ + asm_newabssym.c \ + asm_newscngrp.c asm_scngrp_newsignature.c \ + asm_fill.c asm_align.c asm_addstrz.c \ + asm_addint8.c asm_adduint8.c \ + asm_addint16.c asm_adduint16.c \ + asm_addint32.c asm_adduint32.c \ + asm_addint64.c asm_adduint64.c \ + asm_adduleb128.c asm_addsleb128.c \ + disasm_begin.c disasm_cb.c disasm_end.c disasm_str.c \ + symbolhash.c + +if !MUDFLAP +libasm_pic_a_SOURCES = +am_libasm_pic_a_OBJECTS = $(libasm_a_SOURCES:.c=.os) + +libasm_so_LDLIBS = +if USE_LOCKS +libasm_so_LDLIBS += -lpthread +endif + +libasm_so_SOURCES = +libasm.so: libasm_pic.a libasm.map + $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \ + -Wl,--version-script,$(srcdir)/libasm.map,--no-undefined \ + -Wl,--soname,$@.$(VERSION) \ + ../libebl/libebl.a ../libelf/libelf.so $(libasm_so_LDLIBS) + if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi + ln -fs $@ $@.$(VERSION) + +install: install-am libasm.so + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) libasm.so $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so + ln -fs libasm-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libasm.so.$(VERSION) + ln -fs libasm.so.$(VERSION) $(DESTDIR)$(libdir)/libasm.so + +uninstall: uninstall-am + rm -f $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so + rm -f $(DESTDIR)$(libdir)/libasm.so.$(VERSION) + rm -f $(DESTDIR)$(libdir)/libasm.so + rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils +endif + +noinst_HEADERS = libasmP.h symbolhash.h +EXTRA_DIST = libasm.map + +CLEANFILES += $(am_libasm_pic_a_OBJECTS) libasm.so.$(VERSION) diff --git a/libasm/Makefile.in b/libasm/Makefile.in new file mode 100644 index 0000000..b31c32c --- /dev/null +++ b/libasm/Makefile.in @@ -0,0 +1,666 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(noinst_HEADERS) $(pkginclude_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/eu.am ChangeLog +@MUDFLAP_TRUE@am__append_1 = -fmudflap +@MUDFLAP_FALSE@noinst_PROGRAMS = $(am__EXEEXT_1) +@MUDFLAP_TRUE@am_libasm_pic_a_OBJECTS = +@MUDFLAP_FALSE@@USE_LOCKS_TRUE@am__append_2 = -lpthread +subdir = libasm +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/zip.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)" +LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libasm_a_AR = $(AR) $(ARFLAGS) +libasm_a_LIBADD = +am_libasm_a_OBJECTS = asm_begin.$(OBJEXT) asm_abort.$(OBJEXT) \ + asm_end.$(OBJEXT) asm_error.$(OBJEXT) asm_getelf.$(OBJEXT) \ + asm_newscn.$(OBJEXT) asm_newscn_ingrp.$(OBJEXT) \ + asm_newsubscn.$(OBJEXT) asm_newsym.$(OBJEXT) \ + asm_newcomsym.$(OBJEXT) asm_newabssym.$(OBJEXT) \ + asm_newscngrp.$(OBJEXT) asm_scngrp_newsignature.$(OBJEXT) \ + asm_fill.$(OBJEXT) asm_align.$(OBJEXT) asm_addstrz.$(OBJEXT) \ + asm_addint8.$(OBJEXT) asm_adduint8.$(OBJEXT) \ + asm_addint16.$(OBJEXT) asm_adduint16.$(OBJEXT) \ + asm_addint32.$(OBJEXT) asm_adduint32.$(OBJEXT) \ + asm_addint64.$(OBJEXT) asm_adduint64.$(OBJEXT) \ + asm_adduleb128.$(OBJEXT) asm_addsleb128.$(OBJEXT) \ + disasm_begin.$(OBJEXT) disasm_cb.$(OBJEXT) \ + disasm_end.$(OBJEXT) disasm_str.$(OBJEXT) symbolhash.$(OBJEXT) +libasm_a_OBJECTS = $(am_libasm_a_OBJECTS) +libasm_pic_a_AR = $(AR) $(ARFLAGS) +libasm_pic_a_LIBADD = +libasm_pic_a_OBJECTS = $(am_libasm_pic_a_OBJECTS) +@MUDFLAP_FALSE@am__EXEEXT_1 = libasm.so$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_libasm_so_OBJECTS = +libasm_so_OBJECTS = $(am_libasm_so_OBJECTS) +libasm_so_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libasm_a_SOURCES) $(libasm_pic_a_SOURCES) \ + $(libasm_so_SOURCES) +DIST_SOURCES = $(libasm_a_SOURCES) $(libasm_pic_a_SOURCES) \ + $(libasm_so_SOURCES) +HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUGPRED = @DEBUGPRED@ +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBEBL_SUBDIR = @LIBEBL_SUBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MODVERSION = @MODVERSION@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = 1 +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +base_cpu = @base_cpu@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +eu_version = @eu_version@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +zip_LIBS = @zip_LIBS@ +INCLUDES = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \ + -I$(top_srcdir)/libelf -I$(top_srcdir)/libebl \ + -I$(top_srcdir)/libdw +AM_CFLAGS = -std=gnu99 -Wall -Wshadow $(if \ + $($(*F)_no_Werror),,-Werror) $(if \ + $($(*F)_no_Wunused),,-Wunused -Wextra) $(if \ + $($(*F)_no_Wformat),-Wno-format,-Wformat=2) $($(*F)_CFLAGS) \ + $(am__append_1) +@MUDFLAP_FALSE@libmudflap = +@MUDFLAP_TRUE@libmudflap = -lmudflap +COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage $(no_mudflap.os),\ + $(COMPILE)) + +CLEANFILES = *.gcno *.gcda $(am_libasm_pic_a_OBJECTS) \ + libasm.so.$(VERSION) +textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi +GCC_INCLUDE = -I$(shell $(CC) -print-file-name=include) +lib_LIBRARIES = libasm.a +@MUDFLAP_FALSE@noinst_LIBRARIES = libasm_pic.a +pkginclude_HEADERS = libasm.h +libasm_a_SOURCES = asm_begin.c asm_abort.c asm_end.c asm_error.c \ + asm_getelf.c asm_newscn.c asm_newscn_ingrp.c \ + asm_newsubscn.c asm_newsym.c asm_newcomsym.c \ + asm_newabssym.c \ + asm_newscngrp.c asm_scngrp_newsignature.c \ + asm_fill.c asm_align.c asm_addstrz.c \ + asm_addint8.c asm_adduint8.c \ + asm_addint16.c asm_adduint16.c \ + asm_addint32.c asm_adduint32.c \ + asm_addint64.c asm_adduint64.c \ + asm_adduleb128.c asm_addsleb128.c \ + disasm_begin.c disasm_cb.c disasm_end.c disasm_str.c \ + symbolhash.c + +@MUDFLAP_FALSE@libasm_pic_a_SOURCES = +@MUDFLAP_FALSE@am_libasm_pic_a_OBJECTS = $(libasm_a_SOURCES:.c=.os) +@MUDFLAP_FALSE@libasm_so_LDLIBS = $(am__append_2) +@MUDFLAP_FALSE@libasm_so_SOURCES = +noinst_HEADERS = libasmP.h symbolhash.h +EXTRA_DIST = libasm.map +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/config/eu.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits libasm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits libasm/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLIBRARIES: $(lib_LIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(INSTALL_DATA) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(INSTALL_DATA) $$list2 "$(DESTDIR)$(libdir)" || exit $$?; } + @$(POST_INSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + if test -f $$p; then \ + $(am__strip_dir) \ + echo " ( cd '$(DESTDIR)$(libdir)' && $(RANLIB) $$f )"; \ + ( cd "$(DESTDIR)$(libdir)" && $(RANLIB) $$f ) || exit $$?; \ + else :; fi; \ + done + +uninstall-libLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libdir)' && rm -f "$$files" )"; \ + cd "$(DESTDIR)$(libdir)" && rm -f $$files + +clean-libLIBRARIES: + -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libasm.a: $(libasm_a_OBJECTS) $(libasm_a_DEPENDENCIES) + -rm -f libasm.a + $(libasm_a_AR) libasm.a $(libasm_a_OBJECTS) $(libasm_a_LIBADD) + $(RANLIB) libasm.a +libasm_pic.a: $(libasm_pic_a_OBJECTS) $(libasm_pic_a_DEPENDENCIES) + -rm -f libasm_pic.a + $(libasm_pic_a_AR) libasm_pic.a $(libasm_pic_a_OBJECTS) $(libasm_pic_a_LIBADD) + $(RANLIB) libasm_pic.a + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +@MUDFLAP_TRUE@libasm.so$(EXEEXT): $(libasm_so_OBJECTS) $(libasm_so_DEPENDENCIES) +@MUDFLAP_TRUE@ @rm -f libasm.so$(EXEEXT) +@MUDFLAP_TRUE@ $(LINK) $(libasm_so_OBJECTS) $(libasm_so_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_abort.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addint16.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addint32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addint64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addint8.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addsleb128.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_addstrz.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_adduint16.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_adduint32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_adduint64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_adduint8.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_adduleb128.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_align.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_begin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_end.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_fill.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_getelf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newabssym.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newcomsym.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newscn.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newscn_ingrp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newscngrp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newsubscn.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_newsym.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asm_scngrp_newsignature.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disasm_begin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disasm_cb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disasm_end.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disasm_str.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbolhash.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +@MUDFLAP_TRUE@install: install-am +install-exec: install-exec-am +install-data: install-data-am +@MUDFLAP_TRUE@uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLIBRARIES uninstall-pkgincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLIBRARIES clean-noinstLIBRARIES clean-noinstPROGRAMS \ + ctags distclean distclean-compile distclean-generic \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLIBRARIES install-man install-pdf install-pdf-am \ + install-pkgincludeHEADERS install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLIBRARIES \ + uninstall-pkgincludeHEADERS + + +%.os: %.c %.o +@AMDEP_TRUE@ if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \ +@AMDEP_TRUE@ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \ +@AMDEP_TRUE@ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \ +@AMDEP_TRUE@ rm -f "$(DEPDIR)/$*.Tpo"; \ +@AMDEP_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@AMDEP_TRUE@ fi +@AMDEP_FALSE@ $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $< +@MUDFLAP_FALSE@libasm.so: libasm_pic.a libasm.map +@MUDFLAP_FALSE@ $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \ +@MUDFLAP_FALSE@ -Wl,--version-script,$(srcdir)/libasm.map,--no-undefined \ +@MUDFLAP_FALSE@ -Wl,--soname,$@.$(VERSION) \ +@MUDFLAP_FALSE@ ../libebl/libebl.a ../libelf/libelf.so $(libasm_so_LDLIBS) +@MUDFLAP_FALSE@ if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi +@MUDFLAP_FALSE@ ln -fs $@ $@.$(VERSION) + +@MUDFLAP_FALSE@install: install-am libasm.so +@MUDFLAP_FALSE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MUDFLAP_FALSE@ $(INSTALL_PROGRAM) libasm.so $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so +@MUDFLAP_FALSE@ ln -fs libasm-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libasm.so.$(VERSION) +@MUDFLAP_FALSE@ ln -fs libasm.so.$(VERSION) $(DESTDIR)$(libdir)/libasm.so + +@MUDFLAP_FALSE@uninstall: uninstall-am +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libasm.so.$(VERSION) +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libasm.so +@MUDFLAP_FALSE@ rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libasm/asm_abort.c b/libasm/asm_abort.c new file mode 100644 index 0000000..d12c163 --- /dev/null +++ b/libasm/asm_abort.c @@ -0,0 +1,58 @@ +/* Abort operations on the assembler context, free all resources. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <unistd.h> + +#include <libasmP.h> +#include <libelf.h> + + +int +asm_abort (ctx) + AsmCtx_t *ctx; +{ + if (ctx == NULL) + /* Something went wrong earlier. */ + return -1; + + if (likely (! ctx->textp)) + /* First free the ELF file. We don't care about the result. */ + (void) elf_end (ctx->out.elf); + + /* Now close the temporary file and remove it. */ + if (ctx->fd != -1) + (void) unlink (ctx->tmp_fname); + + /* Free the resources. */ + __libasm_finictx (ctx); + + return 0; +} diff --git a/libasm/asm_addint16.c b/libasm/asm_addint16.c new file mode 100644 index 0000000..5aa8d60 --- /dev/null +++ b/libasm/asm_addint16.c @@ -0,0 +1,29 @@ +/* Add integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 16 + +#include "asm_addint8.c" diff --git a/libasm/asm_addint32.c b/libasm/asm_addint32.c new file mode 100644 index 0000000..25c50ce --- /dev/null +++ b/libasm/asm_addint32.c @@ -0,0 +1,29 @@ +/* Add integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 32 + +#include "asm_addint8.c" diff --git a/libasm/asm_addint64.c b/libasm/asm_addint64.c new file mode 100644 index 0000000..9116d94 --- /dev/null +++ b/libasm/asm_addint64.c @@ -0,0 +1,29 @@ +/* Add integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 64 + +#include "asm_addint8.c" diff --git a/libasm/asm_addint8.c b/libasm/asm_addint8.c new file mode 100644 index 0000000..ff4376b --- /dev/null +++ b/libasm/asm_addint8.c @@ -0,0 +1,120 @@ +/* Add integer to a section. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <byteswap.h> +#include <endian.h> +#include <inttypes.h> +#include <string.h> + +#include <libasmP.h> + +#ifndef SIZE +# define SIZE 8 +#endif + +#define FCT(size) _FCT(size) +#define _FCT(size) asm_addint##size +#define TYPE(size) _TYPE(size) +#define _TYPE(size) int##size##_t +#define BSWAP(size) _BSWAP(size) +#define _BSWAP(size) bswap_##size + + +int +FCT(SIZE) (asmscn, num) + AsmScn_t *asmscn; + TYPE(SIZE) num; +{ + if (asmscn == NULL) + return -1; + + if (asmscn->type == SHT_NOBITS && unlikely (num != 0)) + { + __libasm_seterrno (ASM_E_TYPE); + return -1; + } + + if (unlikely (asmscn->ctx->textp)) + { + // XXX Needs to use backend specified pseudo-ops + if (SIZE == 8) + fprintf (asmscn->ctx->out.file, "\t.byte\t%" PRId8 "\n", (int8_t) num); + else if (SIZE == 16) + fprintf (asmscn->ctx->out.file, "\t.value\t%" PRId16 "\n", + (int16_t) num); + else if (SIZE == 32) + fprintf (asmscn->ctx->out.file, "\t.long\t%" PRId32 "\n", + (int32_t) num); + else + { + // XXX This is not necessary for 64-bit machines + bool is_leb = (elf_getident (asmscn->ctx->out.elf, NULL)[EI_DATA] + == ELFDATA2LSB); + + fprintf (asmscn->ctx->out.file, + "\t.long\t%" PRId32 "\n\t.long\t%" PRId32 "\n", + (int32_t) (is_leb + ? num % 0x100000000ll : num / 0x100000000ll), + (int32_t) (is_leb + ? num / 0x100000000ll : num % 0x100000000ll)); + } + } + else + { +#if SIZE > 8 + bool is_leb = (elf_getident (asmscn->ctx->out.elf, NULL)[EI_DATA] + == ELFDATA2LSB); +#endif + TYPE(SIZE) var = num; + + /* Make sure we have enough room. */ + if (__libasm_ensure_section_space (asmscn, SIZE / 8) != 0) + return -1; + +#if SIZE > 8 + if ((BYTE_ORDER == LITTLE_ENDIAN && !is_leb) + || (BYTE_ORDER == BIG_ENDIAN && is_leb)) + var = BSWAP(SIZE) (var); +#endif + + /* Copy the variable value. */ + if (likely (asmscn->type == SHT_NOBITS)) + memcpy (&asmscn->content->data[asmscn->content->len], &var, SIZE / 8); + + /* Adjust the pointer in the data buffer. */ + asmscn->content->len += SIZE / 8; + + /* Increment the offset in the (sub)section. */ + asmscn->offset += SIZE / 8; + } + + return 0; +} +INTDEF(FCT(SIZE)) diff --git a/libasm/asm_addsleb128.c b/libasm/asm_addsleb128.c new file mode 100644 index 0000000..614ba69 --- /dev/null +++ b/libasm/asm_addsleb128.c @@ -0,0 +1,96 @@ +/* Add signed little endian base 128 integer to a section. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <string.h> + +#include <libasmP.h> + + +int +asm_addsleb128 (asmscn, num) + AsmScn_t *asmscn; + int32_t num; +{ + if (asmscn == NULL) + return -1; + + if (asmscn->type == SHT_NOBITS && unlikely (num != 0)) + { + __libasm_seterrno (ASM_E_TYPE); + return -1; + } + + if (unlikely (asmscn->ctx->textp)) + fprintf (asmscn->ctx->out.file, "\t.sleb128\t%" PRId32 "\n", num); + else + { + char tmpbuf[(sizeof (num) * 8 + 6) / 7]; + char *dest = tmpbuf; + uint32_t byte; + int32_t endval = num >> 31; + + if (num == 0) + byte = 0; + else + while (1) + { + byte = num & 0x7f; + + num >>= 7; + if (num == endval) + /* This is the last byte. */ + break; + + *dest++ = byte | 0x80; + } + + *dest++ = byte; + + /* Number of bytes produced. */ + size_t nbytes = dest - tmpbuf; + + /* Make sure we have enough room. */ + if (__libasm_ensure_section_space (asmscn, nbytes) != 0) + return -1; + + /* Copy the bytes. */ + if (likely (asmscn->type != SHT_NOBITS)) + memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes); + + /* Adjust the pointer in the data buffer. */ + asmscn->content->len += nbytes; + + /* Increment the offset in the (sub)section. */ + asmscn->offset += nbytes; + } + + return 0; +} diff --git a/libasm/asm_addstrz.c b/libasm/asm_addstrz.c new file mode 100644 index 0000000..ddd0354 --- /dev/null +++ b/libasm/asm_addstrz.c @@ -0,0 +1,125 @@ +/* Add string to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +#include <libasmP.h> + + +/* Add zero terminated string STR of size LEN to (sub)section ASMSCN. */ +int +asm_addstrz (asmscn, str, len) + AsmScn_t *asmscn; + const char *str; + size_t len; +{ + if (asmscn == NULL) + return -1; + + if (unlikely (asmscn->type == SHT_NOBITS)) + { + if (len == 0) + { + if (str[0] != '\0') + { + __libasm_seterrno (ASM_E_TYPE); + return -1; + } + } + else + { + size_t cnt; + + for (cnt = 0; cnt < len; ++cnt) + if (str[cnt] != '\0') + { + __libasm_seterrno (ASM_E_TYPE); + return -1; + } + } + } + + if (len == 0) + len = strlen (str) + 1; + + if (unlikely (asmscn->ctx->textp)) + { + bool nextline = true; + + do + { + if (nextline) + { + fputs ("\t.string\t\"", asmscn->ctx->out.file); + nextline = false; + } + + if (*str == '\0') + fputs ("\\000", asmscn->ctx->out.file); + else if (! isascii (*str)) + fprintf (asmscn->ctx->out.file, "\\%03o", + (unsigned int) *((unsigned char *)str)); + else if (*str == '\\') + fputs ("\\\\", asmscn->ctx->out.file); + else if (*str == '\n') + { + fputs ("\\n\"", asmscn->ctx->out.file); + nextline = true; + } + else + fputc (*str, asmscn->ctx->out.file); + + ++str; + } + while (--len > 0 && (len > 1 || *str != '\0')); + + if (! nextline) + fputs ("\"\n", asmscn->ctx->out.file); + } + else + { + /* Make sure there is enough room. */ + if (__libasm_ensure_section_space (asmscn, len) != 0) + return -1; + + /* Copy the string. */ + memcpy (&asmscn->content->data[asmscn->content->len], str, len); + + /* Adjust the pointer in the data buffer. */ + asmscn->content->len += len; + + /* Increment the offset in the (sub)section. */ + asmscn->offset += len; + } + + return 0; +} diff --git a/libasm/asm_adduint16.c b/libasm/asm_adduint16.c new file mode 100644 index 0000000..063e5d4 --- /dev/null +++ b/libasm/asm_adduint16.c @@ -0,0 +1,29 @@ +/* Add unsigned integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 16 + +#include "asm_adduint8.c" diff --git a/libasm/asm_adduint32.c b/libasm/asm_adduint32.c new file mode 100644 index 0000000..6dc814f --- /dev/null +++ b/libasm/asm_adduint32.c @@ -0,0 +1,29 @@ +/* Add unsigned integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 32 + +#include "asm_adduint8.c" diff --git a/libasm/asm_adduint64.c b/libasm/asm_adduint64.c new file mode 100644 index 0000000..71bb16a --- /dev/null +++ b/libasm/asm_adduint64.c @@ -0,0 +1,29 @@ +/* Add unsigned integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#define SIZE 64 + +#include "asm_adduint8.c" diff --git a/libasm/asm_adduint8.c b/libasm/asm_adduint8.c new file mode 100644 index 0000000..c880153 --- /dev/null +++ b/libasm/asm_adduint8.c @@ -0,0 +1,53 @@ +/* Add unsigned integer to a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libasmP.h> + +#ifndef SIZE +# define SIZE 8 +#endif + +#define UFCT(size) _UFCT(size) +#define _UFCT(size) asm_adduint##size +#define FCT(size) _FCT(size) +#define _FCT(size) asm_addint##size +#define UTYPE(size) _UTYPE(size) +#define _UTYPE(size) uint##size##_t +#define TYPE(size) _TYPE(size) +#define _TYPE(size) int##size##_t + + +int +UFCT(SIZE) (asmscn, num) + AsmScn_t *asmscn; + UTYPE(SIZE) num; +{ + return INTUSE(FCT(SIZE)) (asmscn, (TYPE(SIZE)) num); +} diff --git a/libasm/asm_adduleb128.c b/libasm/asm_adduleb128.c new file mode 100644 index 0000000..042c76b --- /dev/null +++ b/libasm/asm_adduleb128.c @@ -0,0 +1,92 @@ +/* Add integer to a section. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <string.h> + +#include "libasmP.h" + + +int +asm_adduleb128 (asmscn, num) + AsmScn_t *asmscn; + uint32_t num; +{ + if (asmscn == NULL) + return -1; + + if (asmscn->type == SHT_NOBITS && unlikely (num != 0)) + { + __libasm_seterrno (ASM_E_TYPE); + return -1; + } + + if (unlikely (asmscn->ctx->textp)) + fprintf (asmscn->ctx->out.file, "\t.uleb128\t%" PRIu32 "\n", num); + else + { + char tmpbuf[(sizeof (num) * 8 + 6) / 7]; + char *dest = tmpbuf; + uint32_t byte; + + while (1) + { + byte = num & 0x7f; + + num >>= 7; + if (num == 0) + /* This is the last byte. */ + break; + + *dest++ = byte | 0x80; + } + + *dest++ = byte; + + /* Number of bytes produced. */ + size_t nbytes = dest - tmpbuf; + + /* Make sure we have enough room. */ + if (__libasm_ensure_section_space (asmscn, nbytes) != 0) + return -1; + + /* Copy the bytes. */ + if (likely (asmscn->type != SHT_NOBITS)) + memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes); + + /* Adjust the pointer in the data buffer. */ + asmscn->content->len += nbytes; + + /* Increment the offset in the (sub)section. */ + asmscn->offset += nbytes; + } + + return 0; +} diff --git a/libasm/asm_align.c b/libasm/asm_align.c new file mode 100644 index 0000000..b5a573b --- /dev/null +++ b/libasm/asm_align.c @@ -0,0 +1,176 @@ +/* Align section. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <sys/param.h> + +#include <libasmP.h> +#include <system.h> + + +int +asm_align (asmscn, value) + AsmScn_t *asmscn; + GElf_Word value; +{ + if (asmscn == NULL) + /* An earlier error. */ + return -1; + + /* The alignment value must be a power of two. */ + if (unlikely (! powerof2 (value))) + { + __libasm_seterrno (ASM_E_INVALID); + return -1; + } + + if (unlikely (asmscn->ctx->textp)) + { + fprintf (asmscn->ctx->out.file, "\t.align %" PRId32 ", ", + (int32_t) value); + if (asmscn->pattern->len == 1) + fprintf (asmscn->ctx->out.file, "%02hhx\n", asmscn->pattern->bytes[0]); + else + { + fputc_unlocked ('"', asmscn->ctx->out.file); + + for (size_t cnt = 0; cnt < asmscn->pattern->len; ++cnt) + fprintf (asmscn->ctx->out.file, "\\x%02hhx", + asmscn->pattern->bytes[cnt]); + + fputs_unlocked ("\"\n", asmscn->ctx->out.file); + } + return 0; + } + + rwlock_wrlock (asmscn->ctx->lock); + + int result = 0; + + /* Fillbytes necessary? */ + if ((asmscn->offset & (value - 1)) != 0) + { + /* Add fillbytes. */ + size_t cnt = value - (asmscn->offset & (value - 1)); + + /* Ensure there is enough room to add the fill bytes. */ + result = __libasm_ensure_section_space (asmscn, cnt); + if (result != 0) + goto out; + + /* Fill in the bytes. We align the pattern according to the + current offset. */ + size_t byteptr = asmscn->offset % asmscn->pattern->len; + + /* Update the total size. */ + asmscn->offset += cnt; + + do + { + asmscn->content->data[asmscn->content->len++] + = asmscn->pattern->bytes[byteptr++]; + + if (byteptr == asmscn->pattern->len) + byteptr = 0; + } + while (--cnt > 0); + } + + /* Remember the maximum alignment for this subsection. */ + if (asmscn->max_align < value) + { + asmscn->max_align = value; + + /* Update the parent as well (if it exists). */ + if (asmscn->subsection_id != 0) + { + rwlock_wrlock (asmscn->data.up->ctx->lock); + + if (asmscn->data.up->max_align < value) + asmscn->data.up->max_align = value; + + rwlock_unlock (asmscn->data.up->ctx->lock); + } + } + + out: + rwlock_unlock (asmscn->ctx->lock); + + return result; +} + + +/* Ensure there are at least LEN bytes available in the output buffer + for ASMSCN. */ +int +__libasm_ensure_section_space (asmscn, len) + AsmScn_t *asmscn; + size_t len; +{ + /* The blocks with the section content are kept in a circular + single-linked list. */ + size_t size; + + if (asmscn->content == NULL) + { + /* This is the first block. */ + size = MAX (2 * len, 960); + + asmscn->content = (struct AsmData *) malloc (sizeof (struct AsmData) + + size); + if (asmscn->content == NULL) + return -1; + + asmscn->content->next = asmscn->content; + } + else + { + struct AsmData *newp; + + if (asmscn->content->maxlen - asmscn->content->len >= len) + /* Nothing to do, there is enough space. */ + return 0; + + size = MAX (2 *len, MIN (32768, 2 * asmscn->offset)); + + newp = (struct AsmData *) malloc (sizeof (struct AsmData) + size); + if (newp == NULL) + return -1; + + newp->next = asmscn->content->next; + asmscn->content = asmscn->content->next = newp; + } + + asmscn->content->len = 0; + asmscn->content->maxlen = size; + + return 0; +} diff --git a/libasm/asm_begin.c b/libasm/asm_begin.c new file mode 100644 index 0000000..b8094dc --- /dev/null +++ b/libasm/asm_begin.c @@ -0,0 +1,181 @@ +/* Create descriptor for assembling. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdio_ext.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) +{ + 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; +} diff --git a/libasm/asm_end.c b/libasm/asm_end.c new file mode 100644 index 0000000..1d815fa --- /dev/null +++ b/libasm/asm_end.c @@ -0,0 +1,610 @@ +/* Finalize operations on the assembler context, free all resources. + Copyright (C) 2002, 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <error.h> +#include <libintl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <libasmP.h> +#include <libelf.h> +#include <system.h> + + +static int +text_end (AsmCtx_t *ctx __attribute__ ((unused))) +{ + if (fclose (ctx->out.file) != 0) + { + __libasm_seterrno (ASM_E_IOERROR); + return -1; + } + + return 0; +} + + +static int +binary_end (AsmCtx_t *ctx) +{ + void *symtab = NULL; + struct Ebl_Strent *symscn_strent = NULL; + struct Ebl_Strent *strscn_strent = NULL; + struct Ebl_Strent *xndxscn_strent = NULL; + Elf_Scn *shstrscn; + struct Ebl_Strent *shstrscn_strent; + size_t shstrscnndx; + size_t symscnndx = 0; + size_t strscnndx = 0; + size_t xndxscnndx = 0; + Elf_Data *data; + Elf_Data *shstrtabdata; + Elf_Data *strtabdata = NULL; + Elf_Data *xndxdata = NULL; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr; + AsmScn_t *asmscn; + int result = 0; + + /* Iterate over the created sections and compute the offsets of the + various subsections and fill in the content. */ + for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext) + { +#if 0 + Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx); +#else + Elf_Scn *scn = asmscn->data.main.scn; +#endif + off_t offset = 0; + AsmScn_t *asmsubscn = asmscn; + + do + { + struct AsmData *content = asmsubscn->content; + bool first = true; + + offset = ((offset + asmsubscn->max_align - 1) + & ~(asmsubscn->max_align - 1)); + + /* Update the offset for this subsection. This field now + stores the offset of the first by in this subsection. */ + asmsubscn->offset = offset; + + /* Note that the content list is circular. */ + if (content != NULL) + do + { + Elf_Data *newdata = elf_newdata (scn); + + if (newdata == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + + newdata->d_buf = content->data; + newdata->d_type = ELF_T_BYTE; + newdata->d_size = content->len; + newdata->d_off = offset; + newdata->d_align = first ? asmsubscn->max_align : 1; + + offset += content->len; + } + while ((content = content->next) != asmsubscn->content); + } + while ((asmsubscn = asmsubscn->subnext) != NULL); + } + + + /* Create the symbol table if necessary. */ + if (ctx->nsymbol_tab > 0) + { + /* Create the symbol table and string table section names. */ + symscn_strent = ebl_strtabadd (ctx->section_strtab, ".symtab", 8); + strscn_strent = ebl_strtabadd (ctx->section_strtab, ".strtab", 8); + + /* Create the symbol string table section. */ + Elf_Scn *strscn = elf_newscn (ctx->out.elf); + strtabdata = elf_newdata (strscn); + shdr = gelf_getshdr (strscn, &shdr_mem); + if (strtabdata == NULL || shdr == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + strscnndx = elf_ndxscn (strscn); + + ebl_strtabfinalize (ctx->symbol_strtab, strtabdata); + + shdr->sh_type = SHT_STRTAB; + assert (shdr->sh_entsize == 0); + + (void) gelf_update_shdr (strscn, shdr); + + /* Create the symbol table section. */ + Elf_Scn *symscn = elf_newscn (ctx->out.elf); + data = elf_newdata (symscn); + shdr = gelf_getshdr (symscn, &shdr_mem); + if (data == NULL || shdr == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + symscnndx = elf_ndxscn (symscn); + + /* We know how many symbols there will be in the symbol table. */ + data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM, + ctx->nsymbol_tab + 1, EV_CURRENT); + symtab = malloc (data->d_size); + if (symtab == NULL) + return -1; + data->d_buf = symtab; + data->d_type = ELF_T_SYM; + data->d_off = 0; + + /* Clear the first entry. */ + GElf_Sym syment; + memset (&syment, '\0', sizeof (syment)); + (void) gelf_update_sym (data, 0, &syment); + + /* Iterate over the symbol table. */ + void *runp = NULL; + int ptr_local = 1; /* Start with index 1; zero remains unused. */ + int ptr_nonlocal = ctx->nsymbol_tab; + uint32_t *xshndx = NULL; + AsmSym_t *sym; + while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL) + if (asm_emit_symbol_p (ebl_string (sym->strent))) + { + assert (ptr_local <= ptr_nonlocal); + + syment.st_name = ebl_strtaboffset (sym->strent); + syment.st_info = GELF_ST_INFO (sym->binding, sym->type); + syment.st_other = 0; + syment.st_value = sym->scn->offset + sym->offset; + syment.st_size = sym->size; + + /* Add local symbols at the beginning, the other from + the end. */ + int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--; + + /* Determine the section index. We have to handle the + overflow correctly. */ + Elf_Scn *scn = (sym->scn->subsection_id == 0 + ? sym->scn->data.main.scn + : sym->scn->data.up->data.main.scn); + + Elf32_Word ndx; + if (unlikely (scn == ASM_ABS_SCN)) + ndx = SHN_ABS; + else if (unlikely (scn == ASM_COM_SCN)) + ndx = SHN_COMMON; + else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE)) + { + if (unlikely (xshndx == NULL)) + { + /* The extended section index section does not yet + exist. */ + Elf_Scn *xndxscn; + + xndxscn = elf_newscn (ctx->out.elf); + xndxdata = elf_newdata (xndxscn); + shdr = gelf_getshdr (xndxscn, &shdr_mem); + if (xndxdata == NULL || shdr == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + xndxscnndx = elf_ndxscn (xndxscn); + + shdr->sh_type = SHT_SYMTAB_SHNDX; + shdr->sh_entsize = sizeof (Elf32_Word); + shdr->sh_addralign = sizeof (Elf32_Word); + shdr->sh_link = symscnndx; + + (void) gelf_update_shdr (xndxscn, shdr); + + xndxscn_strent = ebl_strtabadd (ctx->section_strtab, + ".symtab_shndx", 14); + + /* Note that using 'elf32_fsize' instead of + 'gelf_fsize' here is correct. */ + xndxdata->d_size = elf32_fsize (ELF_T_WORD, + ctx->nsymbol_tab + 1, + EV_CURRENT); + xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size); + if (xshndx == NULL) + return -1; + /* Using ELF_T_WORD here relies on the fact that the + 32- and 64-bit types are the same size. */ + xndxdata->d_type = ELF_T_WORD; + xndxdata->d_off = 0; + } + + /* Store the real section index in the extended setion + index table. */ + assert ((size_t) ptr < ctx->nsymbol_tab + 1); + xshndx[ptr] = ndx; + + /* And signal that this happened. */ + ndx = SHN_XINDEX; + } + syment.st_shndx = ndx; + + /* Remember where we put the symbol. */ + sym->symidx = ptr; + + (void) gelf_update_sym (data, ptr, &syment); + } + + assert (ptr_local == ptr_nonlocal + 1); + + shdr->sh_type = SHT_SYMTAB; + shdr->sh_link = strscnndx; + shdr->sh_info = ptr_local; + shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT); + shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1, + EV_CURRENT); + + (void) gelf_update_shdr (symscn, shdr); + } + + + /* Create the section header string table section and fill in the + references in the section headers. */ + shstrscn = elf_newscn (ctx->out.elf); + shstrtabdata = elf_newdata (shstrscn); + shdr = gelf_getshdr (shstrscn, &shdr_mem); + if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + + + /* Add the name of the section header string table. */ + shstrscn_strent = ebl_strtabadd (ctx->section_strtab, ".shstrtab", 10); + + ebl_strtabfinalize (ctx->section_strtab, shstrtabdata); + + shdr->sh_type = SHT_STRTAB; + assert (shdr->sh_entsize == 0); + shdr->sh_name = ebl_strtaboffset (shstrscn_strent); + + (void) gelf_update_shdr (shstrscn, shdr); + + + /* Create the section groups. */ + if (ctx->groups != NULL) + { + AsmScnGrp_t *runp = ctx->groups->next; + + do + { + Elf_Scn *scn; + Elf32_Word *grpdata; + + scn = runp->scn; + assert (scn != NULL); + shdr = gelf_getshdr (scn, &shdr_mem); + assert (shdr != NULL); + + data = elf_newdata (scn); + if (data == NULL) + { + __libasm_seterrno (ASM_E_LIBELF); + return -1; + } + + /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize' + here. */ + data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1, + EV_CURRENT); + grpdata = data->d_buf = malloc (data->d_size); + if (grpdata == NULL) + return -1; + data->d_type = ELF_T_WORD; + data->d_off = 0; + data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT); + + /* The first word of the section is filled with the flag word. */ + *grpdata++ = runp->flags; + + if (runp->members != NULL) + { + AsmScn_t *member = runp->members->data.main.next_in_group; + + do + { + /* Only sections, not subsections, can be registered + as member of a group. The subsections get + automatically included. */ + assert (member->subsection_id == 0); + + *grpdata++ = elf_ndxscn (member->data.main.scn); + } + while ((member = member->data.main.next_in_group) + != runp->members->data.main.next_in_group); + } + + /* Construct the section header. */ + shdr->sh_name = ebl_strtaboffset (runp->strent); + shdr->sh_type = SHT_GROUP; + shdr->sh_flags = 0; + shdr->sh_link = symscnndx; + /* If the user did not specify a signature we use the initial + empty symbol in the symbol table as the signature. */ + shdr->sh_info = (runp->signature != NULL + ? runp->signature->symidx : 0); + + (void) gelf_update_shdr (scn, shdr); + } + while ((runp = runp->next) != ctx->groups->next); + } + + + /* Add the name to the symbol section. */ + if (likely (symscnndx != 0)) + { + Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx); + + shdr = gelf_getshdr (scn, &shdr_mem); + + shdr->sh_name = ebl_strtaboffset (symscn_strent); + + (void) gelf_update_shdr (scn, shdr); + + + /* Add the name to the string section. */ + assert (strscnndx != 0); + scn = elf_getscn (ctx->out.elf, strscnndx); + + shdr = gelf_getshdr (scn, &shdr_mem); + + shdr->sh_name = ebl_strtaboffset (strscn_strent); + + (void) gelf_update_shdr (scn, shdr); + + + /* Add the name to the extended symbol index section. */ + if (xndxscnndx != 0) + { + scn = elf_getscn (ctx->out.elf, xndxscnndx); + + shdr = gelf_getshdr (scn, &shdr_mem); + + shdr->sh_name = ebl_strtaboffset (xndxscn_strent); + + (void) gelf_update_shdr (scn, shdr); + } + } + + + /* Iterate over the created sections and fill in the names. */ + for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext) + { + shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem); + /* This better should not fail. */ + assert (shdr != NULL); + + shdr->sh_name = ebl_strtaboffset (asmscn->data.main.strent); + + /* We now know the maximum alignment. */ + shdr->sh_addralign = asmscn->max_align; + + (void) gelf_update_shdr (asmscn->data.main.scn, shdr); + } + + /* Put the reference to the section header string table in the ELF + header. */ + ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem); + assert (ehdr != NULL); + + shstrscnndx = elf_ndxscn (shstrscn); + if (unlikely (shstrscnndx > SHN_HIRESERVE) + || unlikely (shstrscnndx == SHN_XINDEX)) + { + /* The index of the section header string sectio is too large. */ + Elf_Scn *scn = elf_getscn (ctx->out.elf, 0); + + /* Get the header for the zeroth section. */ + shdr = gelf_getshdr (scn, &shdr_mem); + /* This better does not fail. */ + assert (shdr != NULL); + + /* The sh_link field of the zeroth section header contains the value. */ + shdr->sh_link = shstrscnndx; + + (void) gelf_update_shdr (scn, shdr); + + /* This is the sign for the overflow. */ + ehdr->e_shstrndx = SHN_XINDEX; + } + else + ehdr->e_shstrndx = elf_ndxscn (shstrscn); + + gelf_update_ehdr (ctx->out.elf, ehdr); + + /* Write out the ELF file. */ + if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP)) < 0) + { + __libasm_seterrno (ASM_E_LIBELF); + result = -1; + } + + /* We do not need the section header and symbol string tables anymore. */ + free (shstrtabdata->d_buf); + if (strtabdata != NULL) + free (strtabdata->d_buf); + /* We might have allocated the extended symbol table index. */ + if (xndxdata != NULL) + free (xndxdata->d_buf); + + /* Free section groups memory. */ + AsmScnGrp_t *scngrp = ctx->groups; + if (scngrp != NULL) + do + free (elf_getdata (scngrp->scn, NULL)->d_buf); + while ((scngrp = scngrp->next) != ctx->groups); + + /* Finalize the ELF handling. */ + if (unlikely (elf_end (ctx->out.elf)) != 0) + { + __libasm_seterrno (ASM_E_LIBELF); + result = -1; + } + + /* Free the temporary resources. */ + free (symtab); + + return result; +} + + +int +asm_end (ctx) + AsmCtx_t *ctx; +{ + int result; + + if (ctx == NULL) + /* Something went wrong earlier. */ + return -1; + + result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx); + if (result != 0) + return result; + + /* Make the new file globally readable and user/group-writable. */ + if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0) + { + __libasm_seterrno (ASM_E_CANNOT_CHMOD); + return -1; + } + + /* Rename output file. */ + if (rename (ctx->tmp_fname, ctx->fname) != 0) + { + __libasm_seterrno (ASM_E_CANNOT_RENAME); + return -1; + } + + /* Free the resources. */ + __libasm_finictx (ctx); + + return 0; +} + + +static void +free_section (AsmScn_t *scnp) +{ + void *oldp; + + if (scnp->subnext != NULL) + free_section (scnp->subnext); + + struct AsmData *data = scnp->content; + if (data != NULL) + do + { + oldp = data; + data = data->next; + free (oldp); + } + while (oldp != scnp->content); + + free (scnp); +} + + +void +__libasm_finictx (ctx) + AsmCtx_t *ctx; +{ + /* Iterate through section table and free individual entries. */ + AsmScn_t *scn = ctx->section_list; + while (scn != NULL) + { + AsmScn_t *oldp = scn; + scn = scn->allnext; + free_section (oldp); + } + + /* Free the resources of the symbol table. */ + void *runp = NULL; + AsmSym_t *sym; + while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL) + free (sym); + asm_symbol_tab_free (&ctx->symbol_tab); + + + /* Free section groups. */ + AsmScnGrp_t *scngrp = ctx->groups; + if (scngrp != NULL) + do + { + AsmScnGrp_t *oldp = scngrp; + + scngrp = scngrp->next; + free (oldp); + } + while (scngrp != ctx->groups); + + + if (unlikely (ctx->textp)) + { + /* Close the stream. */ + fclose (ctx->out.file); + } + else + { + /* Close the output file. */ + /* XXX We should test for errors here but what would we do if we'd + find any. */ + (void) close (ctx->fd); + + /* And the string tables. */ + ebl_strtabfree (ctx->section_strtab); + ebl_strtabfree (ctx->symbol_strtab); + } + + /* Initialize the lock. */ + rwlock_fini (ctx->lock); + + /* Finally free the data structure. */ + free (ctx); +} diff --git a/libasm/asm_error.c b/libasm/asm_error.c new file mode 100644 index 0000000..4d249e9 --- /dev/null +++ b/libasm/asm_error.c @@ -0,0 +1,93 @@ +/* Error handling in libasm. + Copyright (C) 2002, 2004, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libintl.h> +#include <stdbool.h> +#include <stdlib.h> + +#include "libasmP.h" + + +/* This is the key for the thread specific memory. */ +static __thread int global_error; + + +int +asm_errno (void) +{ + int result = global_error; + global_error = ASM_E_NOERROR; + return result; +} + + +void +__libasm_seterrno (value) + int value; +{ + global_error = value; +} + + +/* Return the appropriate message for the error. */ +static const char *msgs[ASM_E_NUM] = +{ + [ASM_E_NOERROR] = N_("no error"), + [ASM_E_NOMEM] = N_("out of memory"), + [ASM_E_CANNOT_CREATE] = N_("cannot create output file"), + [ASM_E_INVALID] = N_("invalid parameter"), + [ASM_E_CANNOT_CHMOD] = N_("cannot change mode of output file"), + [ASM_E_CANNOT_RENAME] = N_("cannot rename output file"), + [ASM_E_DUPLSYM] = N_("duplicate symbol"), + [ASM_E_TYPE] = N_("invalid section type for operation"), + [ASM_E_IOERROR] = N_("error during output of data"), + [ASM_E_ENOSUP] = N_("no backend support available"), +}; + +const char * +asm_errmsg (error) + int error; +{ + int last_error = global_error; + + if (error < -1) + return _("unknown error"); + if (error == 0 && last_error == 0) + /* No error. */ + return NULL; + + if (error != -1) + last_error = error; + + if (last_error == ASM_E_LIBELF) + return elf_errmsg (-1); + + return _(msgs[last_error]); +} diff --git a/libasm/asm_fill.c b/libasm/asm_fill.c new file mode 100644 index 0000000..66f7134 --- /dev/null +++ b/libasm/asm_fill.c @@ -0,0 +1,74 @@ +/* Determine fill pattern for a section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include <libasmP.h> +#include <system.h> + + +int +asm_fill (asmscn, bytes, len) + AsmScn_t *asmscn; + void *bytes; + size_t len; +{ + struct FillPattern *pattern; + struct FillPattern *old_pattern; + + if (asmscn == NULL) + /* Some earlier error. */ + return -1; + + if (bytes == NULL) + /* Use the default pattern. */ + pattern = (struct FillPattern *) __libasm_default_pattern; + else + { + /* Allocate appropriate memory. */ + pattern = (struct FillPattern *) malloc (sizeof (struct FillPattern) + + len); + if (pattern == NULL) + return -1; + + pattern->len = len; + memcpy (pattern->bytes, bytes, len); + } + + old_pattern = asmscn->pattern; + asmscn->pattern = pattern; + + /* Free the old data structure if we have allocated it. */ + if (old_pattern != __libasm_default_pattern) + free (old_pattern); + + return 0; +} diff --git a/libasm/asm_getelf.c b/libasm/asm_getelf.c new file mode 100644 index 0000000..df5cffd --- /dev/null +++ b/libasm/asm_getelf.c @@ -0,0 +1,41 @@ +/* Return ELF descriptor associated with the assembler context. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> + +#include <libasmP.h> + + +Elf * +asm_getelf (ctx) + AsmCtx_t *ctx; +{ + return ctx != NULL ? ctx->out.elf : NULL; +} diff --git a/libasm/asm_newabssym.c b/libasm/asm_newabssym.c new file mode 100644 index 0000000..1dacb01 --- /dev/null +++ b/libasm/asm_newabssym.c @@ -0,0 +1,133 @@ +/* Create new ABS symbol. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libasmP.h> +#include <system.h> + + +/* Object for special COMMON section. */ +static const AsmScn_t __libasm_abs_scn = + { + .data = { + .main = { + .scn = ASM_ABS_SCN + } + } + }; + + +AsmSym_t * +asm_newabssym (ctx, name, size, value, type, binding) + AsmCtx_t *ctx; + const char *name; + GElf_Xword size; + GElf_Addr value; + int type; + int binding; +{ + AsmSym_t *result; + + if (ctx == NULL) + /* Something went wrong before. */ + return NULL; + + /* Common symbols are public. Therefore the user must provide a + name. */ + if (name == NULL) + { + __libasm_seterrno (ASM_E_INVALID); + return NULL; + } + + rwlock_wrlock (ctx->lock); + + result = (AsmSym_t *) malloc (sizeof (AsmSym_t)); + if (result == NULL) + return NULL; + + result->scn = (AsmScn_t *) &__libasm_abs_scn; + result->size = size; + result->type = type; + result->binding = binding; + result->symidx = 0; + result->strent = ebl_strtabadd (ctx->symbol_strtab, name, 0); + + /* The value of an ABS symbol must not be modified. Since there are + no subsection and the initial offset of the section is 0 we can + get the alignment recorded by storing it into the offset + field. */ + result->offset = value; + + if (unlikely (ctx->textp)) + { + /* An absolute symbol can be defined by giving a symbol a + specific value. */ + if (binding == STB_GLOBAL) + fprintf (ctx->out.file, "\t.globl %s\n", name); + else if (binding == STB_WEAK) + fprintf (ctx->out.file, "\t.weak %s\n", name); + + if (type == STT_OBJECT) + fprintf (ctx->out.file, "\t.type %s,@object\n", name); + else if (type == STT_FUNC) + fprintf (ctx->out.file, "\t.type %s,@function\n", name); + + fprintf (ctx->out.file, "%s = %llu\n", + name, (unsigned long long int) value); + + if (size != 0) + fprintf (ctx->out.file, "\t.size %s, %llu\n", + name, (unsigned long long int) size); + } + else + { + /* Put the symbol in the hash table so that we can later find it. */ + if (asm_symbol_tab_insert (&ctx->symbol_tab, elf_hash (name), result) + != 0) + { + /* The symbol already exists. */ + __libasm_seterrno (ASM_E_DUPLSYM); + free (result); + result = NULL; + } + else if (name != NULL && asm_emit_symbol_p (name)) + /* Only count non-private symbols. */ + ++ctx->nsymbol_tab; + } + + rwlock_unlock (ctx->lock); + + return result; +} diff --git a/libasm/asm_newcomsym.c b/libasm/asm_newcomsym.c new file mode 100644 index 0000000..4a7144e --- /dev/null +++ b/libasm/asm_newcomsym.c @@ -0,0 +1,114 @@ +/* Create new COMMON symbol. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libasmP.h> +#include <system.h> + + +/* Object for special COMMON section. */ +static const AsmScn_t __libasm_com_scn = + { + .data = { + .main = { + .scn = ASM_COM_SCN + } + } + }; + + +AsmSym_t * +asm_newcomsym (ctx, name, size, align) + AsmCtx_t *ctx; + const char *name; + GElf_Xword size; + GElf_Addr align; +{ + AsmSym_t *result; + + if (ctx == NULL) + /* Something went wrong before. */ + return NULL; + + /* Common symbols are public. Therefore the user must provide a + name. */ + if (name == NULL) + { + __libasm_seterrno (ASM_E_INVALID); + return NULL; + } + + rwlock_wrlock (ctx->lock); + + result = (AsmSym_t *) malloc (sizeof (AsmSym_t)); + if (result == NULL) + return NULL; + + result->scn = (AsmScn_t *) &__libasm_com_scn; + result->size = size; + /* XXX Do we have to allow a different type? */ + result->type = STT_OBJECT; + /* XXX Do we have to allow a different binding? */ + result->binding = STB_GLOBAL; + result->symidx = 0; + result->strent = ebl_strtabadd (ctx->symbol_strtab, name, 0); + + /* The value of a COM symbol is the alignment. Since there are no + subsection and the initial offset of the section is 0 we can get + the alignment recorded by storing it into the offset field. */ + result->offset = align; + + if (unlikely (ctx->textp)) + fprintf (ctx->out.file, "\t.comm %s, %" PRIuMAX ", %" PRIuMAX "\n", + name, (uintmax_t) size, (uintmax_t) align); + else + { + /* Put the symbol in the hash table so that we can later find it. */ + if (asm_symbol_tab_insert (&ctx->symbol_tab, elf_hash (name), result) + != 0) + { + /* The symbol already exists. */ + __libasm_seterrno (ASM_E_DUPLSYM); + free (result); + result = NULL; + } + else if (name != NULL && asm_emit_symbol_p (name)) + /* Only count non-private symbols. */ + ++ctx->nsymbol_tab; + } + + rwlock_unlock (ctx->lock); + + return result; +} diff --git a/libasm/asm_newscn.c b/libasm/asm_newscn.c new file mode 100644 index 0000000..dd48d2b --- /dev/null +++ b/libasm/asm_newscn.c @@ -0,0 +1,212 @@ +/* Create new section in output file. + Copyright (C) 2002-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <error.h> +#include <libintl.h> +#include <stdlib.h> +#include <string.h> + +#include <libasmP.h> +#include <libelf.h> +#include <system.h> + + +/* Memory for the default pattern. The type uses a flexible array + which does work well with a static initializer. So we play some + dirty tricks here. */ +static const struct +{ + struct FillPattern pattern; + char zero; +} xdefault_pattern = + { + .pattern = + { + .len = 1 + }, + .zero = '\0' + }; +const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern; + + +static AsmScn_t * +text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags) +{ + /* Buffer where we construct the flag string. */ + char flagstr[sizeof (GElf_Xword) * 8 + 5]; + char *wp = flagstr; + const char *typestr = ""; + + /* Only write out the flag string if this is the first time the + section is selected. Some assemblers cannot cope with the + .section pseudo-op otherwise. */ + wp = stpcpy (wp, ", \""); + + if (flags & SHF_WRITE) + *wp++ = 'w'; + if (flags & SHF_ALLOC) + *wp++ = 'a'; + if (flags & SHF_EXECINSTR) + *wp++ = 'x'; + if (flags & SHF_MERGE) + *wp++ = 'M'; + if (flags & SHF_STRINGS) + *wp++ = 'S'; + if (flags & SHF_LINK_ORDER) + *wp++ = 'L'; + + *wp++ = '"'; + + if (type == SHT_PROGBITS) + typestr = ",@progbits"; + else if (type == SHT_NOBITS) + typestr = ",@nobits"; + + /* Terminate the string. */ + *wp = '\0'; + + fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n", + result->name, flagstr, typestr); + + return result; +} + + +static AsmScn_t * +binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags, + size_t scnname_len) +{ + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + Elf_Scn *scn; + + /* The initial subsection has the number zero. */ + result->subsection_id = 0; + + /* We start at offset zero. */ + result->offset = 0; + /* And generic alignment. */ + result->max_align = 1; + + /* No output yet. */ + result->content = NULL; + + /* Put the default fill pattern in place. */ + result->pattern = (struct FillPattern *) __libasm_default_pattern; + + /* There are no subsections so far. */ + result->subnext = NULL; + + /* Add the name to the section header string table. */ + result->data.main.strent = ebl_strtabadd (result->ctx->section_strtab, + result->name, scnname_len); + assert (result->data.main.strent != NULL); + + /* Create the new ELF section. */ + result->data.main.scn = scn = elf_newscn (result->ctx->out.elf); + if (scn == NULL) + { + free (result); + __libasm_seterrno (ASM_E_LIBELF); + return NULL; + } + + /* Not part of a section group (yet). */ + result->data.main.next_in_group = NULL; + + /* Remember the flags. */ + shdr = gelf_getshdr (scn, &shdr_mem); + + shdr->sh_flags = flags; + result->type = shdr->sh_type = type; + + (void) gelf_update_shdr (scn, shdr); + + return result; +} + + +AsmScn_t * +asm_newscn (ctx, scnname, type, flags) + AsmCtx_t *ctx; + const char *scnname; + GElf_Word type; + GElf_Xword flags; +{ + size_t scnname_len = strlen (scnname) + 1; + AsmScn_t *result; + + /* If no context is given there might be an earlier error. */ + if (ctx == NULL) + return NULL; + + /* Check whether only flags are set which areselectable by the user. */ + if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE + | SHF_STRINGS | SHF_LINK_ORDER)) != 0) + /* We allow only two section types: data and data without file + representation. */ + || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS))) + { + __libasm_seterrno (ASM_E_INVALID); + return NULL; + } + + rwlock_wrlock (ctx->lock); + + /* This is a new section. */ + result = (AsmScn_t *) malloc (sizeof (AsmScn_t) + scnname_len); + if (result != NULL) + { + /* Add the name. */ + memcpy (result->name, scnname, scnname_len); + + /* Add the reference to the context. */ + result->ctx = ctx; + + /* Perform operations according to output mode. */ + result = (unlikely (ctx->textp) + ? text_newscn (result, type, flags) + : binary_newscn (result, type, flags, scnname_len)); + + /* If everything went well finally add the new section to the hash + table. */ + if (result != NULL) + { + result->allnext = ctx->section_list; + ctx->section_list = result; + } + } + + rwlock_unlock (ctx->lock); + + return result; +} +INTDEF(asm_newscn) diff --git a/libasm/asm_newscn_ingrp.c b/libasm/asm_newscn_ingrp.c new file mode 100644 index 0000000..c17e22e --- /dev/null +++ b/libasm/asm_newscn_ingrp.c @@ -0,0 +1,78 @@ +/* Create new section, which is member of a group, in output file. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> + +#include "libasmP.h" + + +AsmScn_t * +asm_newscn_ingrp (ctx, scnname, type, flags, grp) + AsmCtx_t *ctx; + const char *scnname; + GElf_Word type; + GElf_Xword flags; + AsmScnGrp_t *grp; +{ + AsmScn_t *result = INTUSE (asm_newscn) (ctx, scnname, type, flags); + + if (likely (result != NULL)) + { + /* We managed to create a section group. Add it to the section + group. */ + if (grp->nmembers == 0) + { + assert (grp->members == NULL); + grp->members = result->data.main.next_in_group = result; + } + else + { + result->data.main.next_in_group + = grp->members->data.main.next_in_group; + grp->members = grp->members->data.main.next_in_group = result; + } + + ++grp->nmembers; + + /* Set the SHF_GROUP flag. */ + if (likely (! ctx->textp)) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (result->data.main.scn, &shdr_mem); + + assert (shdr != NULL); + shdr->sh_flags |= SHF_GROUP; + + (void) gelf_update_shdr (result->data.main.scn, shdr); + } + } + + return result; +} diff --git a/libasm/asm_newscngrp.c b/libasm/asm_newscngrp.c new file mode 100644 index 0000000..1eed25c --- /dev/null +++ b/libasm/asm_newscngrp.c @@ -0,0 +1,102 @@ +/* Create new section group. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "libasmP.h" +#include <system.h> + + + +AsmScnGrp_t * +asm_newscngrp (ctx, grpname, signature, flags) + AsmCtx_t *ctx; + const char *grpname; + AsmSym_t *signature; + Elf32_Word flags; +{ + AsmScnGrp_t *result; + size_t grpname_len = strlen (grpname) + 1; + + if (ctx == NULL) + return NULL; + + if ((flags & ~GRP_COMDAT) != 0) + { + /* This is not a supported flag. */ + __libasm_seterrno (ASM_E_INVALID); + return NULL; + } + + result = (AsmScnGrp_t *) malloc (sizeof (AsmScnGrp_t) + grpname_len); + if (result == NULL) + return NULL; + + result->signature = signature; + result->members = NULL; + result->nmembers = 0; + result->flags = flags; + + memcpy (result->name, grpname, grpname_len); + result->strent = ebl_strtabadd (ctx->section_strtab, result->name, + grpname_len); + + if (unlikely (ctx->textp)) + // XXX TBI. What is the format? + abort (); + else + { + result->scn = elf_newscn (ctx->out.elf); + if (result->scn == NULL) + { + /* Couldn't allocate a new section. */ + __libasm_seterrno (ASM_E_LIBELF); + free (result); + return NULL; + } + } + + /* Enqueue is the context data structure. */ + if (ctx->ngroups == 0) + { + assert (ctx->groups == NULL); + ctx->groups = result->next = result; + } + else + { + result->next = ctx->groups->next; + ctx->groups = ctx->groups->next = result; + } + ++ctx->ngroups; + + return result; +} diff --git a/libasm/asm_newsubscn.c b/libasm/asm_newsubscn.c new file mode 100644 index 0000000..d1a86dd --- /dev/null +++ b/libasm/asm_newsubscn.c @@ -0,0 +1,96 @@ +/* Create new subsection section in given section. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> + +#include <libasmP.h> +#include <system.h> + + +AsmScn_t * +asm_newsubscn (asmscn, nr) + AsmScn_t *asmscn; + unsigned int nr; +{ + AsmScn_t *runp; + AsmScn_t *newp; + + /* Just return if no section is given. The error must have been + somewhere else. */ + if (asmscn == NULL) + return NULL; + + /* Determine whether there is already a subsection with this number. */ + runp = asmscn->subsection_id == 0 ? asmscn : asmscn->data.up; + while (1) + { + if (runp->subsection_id == nr) + /* Found it. */ + return runp; + + if (runp->subnext == NULL || runp->subnext->subsection_id > nr) + break; + + runp = runp->subnext; + } + + newp = (AsmScn_t *) malloc (sizeof (AsmScn_t)); + if (newp == NULL) + return NULL; + + /* Same assembler context than the original section. */ + newp->ctx = runp->ctx; + + /* User provided the subsectio nID. */ + newp->subsection_id = nr; + + /* Inherit the parent's type. */ + newp->type = runp->type; + + /* Pointer to the zeroth subsection. */ + newp->data.up = runp->subsection_id == 0 ? runp : runp->data.up; + + /* We start at offset zero. */ + newp->offset = 0; + /* And generic alignment. */ + newp->max_align = 1; + + /* No output yet. */ + newp->content = NULL; + + /* Inherit the fill pattern from the section this one is derived from. */ + newp->pattern = asmscn->pattern; + + /* Enqueue at the right position in the list. */ + newp->subnext = runp->subnext; + runp->subnext = newp; + + return newp; +} diff --git a/libasm/asm_newsym.c b/libasm/asm_newsym.c new file mode 100644 index 0000000..e2727b1 --- /dev/null +++ b/libasm/asm_newsym.c @@ -0,0 +1,135 @@ +/* Define new symbol for current position in given section. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libasmP.h> +#include <system.h> + + +AsmSym_t * +asm_newsym (asmscn, name, size, type, binding) + AsmScn_t *asmscn; + const char *name; + GElf_Xword size; + int type; + int binding; +{ +#define TEMPSYMLEN 10 + char tempsym[TEMPSYMLEN]; + AsmSym_t *result; + + if (asmscn == NULL) + /* Something went wrong before. */ + return NULL; + + /* Generate a temporary symbol if necessary. */ + if (name == NULL) + { + /* If a local symbol name is created the symbol better have + local binding. */ + if (binding != STB_LOCAL) + { + __libasm_seterrno (ASM_E_INVALID); + return NULL; + } + + // XXX This requires getting the format from the machine backend. */ + snprintf (tempsym, TEMPSYMLEN, ".L%07u", asmscn->ctx->tempsym_count++); + + name = tempsym; + } + + size_t name_len = strlen (name) + 1; + + result = (AsmSym_t *) malloc (sizeof (AsmSym_t) + name_len); + if (result == NULL) + return NULL; + + rwlock_wrlock (asmscn->ctx->lock); + + result->scn = asmscn; + result->offset = asmscn->offset; + result->size = size; + result->type = type; + result->binding = binding; + result->symidx = 0; + result->strent = ebl_strtabadd (asmscn->ctx->symbol_strtab, + memcpy (result + 1, name, name_len), 0); + + if (unlikely (asmscn->ctx->textp)) + { + /* We are only interested in the name and don't need to know whether + it is a local name or not. */ + /* First print the binding pseudo-op. */ + if (binding == STB_GLOBAL) + fprintf (asmscn->ctx->out.file, "\t.globl\t%s\n", name); + else if (binding == STB_WEAK) + fprintf (asmscn->ctx->out.file, "\t.weak\t%s\n", name); + + /* Next the symbol type. */ + if (type == STT_OBJECT) + fprintf (asmscn->ctx->out.file, "\t.type\t%s,@object\n", name); + else if (type == STT_FUNC) + fprintf (asmscn->ctx->out.file, "\t.type\t%s,@function\n", name); + + /* Finally the size and the label. */ + fprintf (asmscn->ctx->out.file, "\t.size\t%s,%" PRIuMAX "\n%s:\n", + name, (uintmax_t) size, name); + } + else + { + /* Put the symbol in the hash table so that we can later find it. */ + if (asm_symbol_tab_insert (&asmscn->ctx->symbol_tab, elf_hash (name), + result) != 0) + { + /* The symbol already exists. */ + __libasm_seterrno (ASM_E_DUPLSYM); + /* Note that we can free the entry since there must be no + reference in the string table to the string. We can only + fail to insert the symbol into the symbol table if there + is already a symbol with this name. In this case the + ebl_strtabadd function would use the previously provided + name. */ + free (result); + result = NULL; + } + else if (name != tempsym && asm_emit_symbol_p (name)) + /* Only count non-private symbols. */ + ++asmscn->ctx->nsymbol_tab; + } + + rwlock_unlock (asmscn->ctx->lock); + + return result; +} diff --git a/libasm/asm_scngrp_newsignature.c b/libasm/asm_scngrp_newsignature.c new file mode 100644 index 0000000..9908e40 --- /dev/null +++ b/libasm/asm_scngrp_newsignature.c @@ -0,0 +1,45 @@ +/* Update signature of section group. + Copyright (C) 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libasmP.h" + + +int +asm_scngrp_newsignature (grp, signature) + AsmScnGrp_t *grp; + AsmSym_t *signature; +{ + if (grp == NULL || signature == NULL) + return 1; + + grp->signature = signature; + + return 0; +} diff --git a/libasm/disasm_begin.c b/libasm/disasm_begin.c new file mode 100644 index 0000000..5b98b2a --- /dev/null +++ b/libasm/disasm_begin.c @@ -0,0 +1,61 @@ +/* Create context descriptor for disassembler. + Copyright (C) 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> + +#include "libasmP.h" +#include "../libebl/libeblP.h" + + +DisasmCtx_t * +disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb) +{ + if (ebl == NULL) + return NULL; + + if (ebl->disasm == NULL) + { + __libasm_seterrno (ASM_E_ENOSUP); + return NULL; + } + + DisasmCtx_t *ctx = (DisasmCtx_t *) malloc (sizeof (DisasmCtx_t)); + if (ctx == NULL) + { + __libasm_seterrno (ASM_E_NOMEM); + return NULL; + } + + ctx->ebl = ebl; + ctx->elf = elf; + ctx->symcb = symcb; + + return ctx; +} diff --git a/libasm/disasm_cb.c b/libasm/disasm_cb.c new file mode 100644 index 0000000..5610125 --- /dev/null +++ b/libasm/disasm_cb.c @@ -0,0 +1,176 @@ +/* Copyright (C) 2005, 2007, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#include "libasmP.h" +#include "../libebl/libeblP.h" + + +struct symtoken +{ + DisasmCtx_t *ctx; + void *symcbarg; +}; + + +static int +default_elf_getsym (GElf_Addr addr, Elf32_Word scnndx, GElf_Addr value, + char **buf, size_t *buflen, void *arg) +{ + struct symtoken *symtoken = (struct symtoken *) arg; + + /* First try the user provided function. */ + if (symtoken->ctx->symcb != NULL) + { + int res = symtoken->ctx->symcb (addr, scnndx, value, buf, buflen, + symtoken->symcbarg); + if (res >= 0) + return res; + } + + // XXX Look up in ELF file. + + return -1; +} + + +struct symaddrpair +{ + GElf_Addr addr; + const char *name; +}; + + +static void +read_symtab_exec (DisasmCtx_t *ctx) +{ + /* We simply use all we can get our hands on. This will produce + some duplicate information but this is no problem, we simply + ignore the latter definitions. */ + Elf_Scn *scn= NULL; + while ((scn = elf_nextscn (ctx->elf, scn)) != NULL) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + Elf_Data *data; + if (shdr == NULL || shdr->sh_type != SHT_SYMTAB + || (data = elf_getdata (scn, NULL)) == NULL) + continue; + + int xndxscnidx = elf_scnshndx (scn); + Elf_Data *xndxdata = NULL; + if (xndxscnidx > 0) + xndxdata = elf_getdata (elf_getscn (ctx->elf, xndxscnidx), NULL); + + /* Iterate over all symbols. Add all defined symbols. */ + int nsyms = shdr->sh_size / shdr->sh_entsize; + for (int cnt = 1; cnt < nsyms; ++cnt) + { + Elf32_Word xshndx; + GElf_Sym sym_mem; + GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, + &xshndx); + if (sym == NULL) + continue; + + /* Undefined symbols are useless here. */ + if (sym->st_shndx == SHN_UNDEF) + continue; + + + } + } +} + + +static void +read_symtab (DisasmCtx_t *ctx) +{ + /* Find the symbol table(s). */ + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (ctx->elf, &ehdr_mem); + if (ehdr == NULL) + return; + + switch (ehdr->e_type) + { + case ET_EXEC: + case ET_DYN: + read_symtab_exec (ctx); + break; + + case ET_REL: + // XXX Handle + break; + + default: + break; + } +} + + +static int +null_elf_getsym (GElf_Addr addr __attribute__ ((unused)), + Elf32_Word scnndx __attribute__ ((unused)), + GElf_Addr value __attribute__ ((unused)), + char **buf __attribute__ ((unused)), + size_t *buflen __attribute__ ((unused)), + void *arg __attribute__ ((unused))) +{ + return -1; +} + + +int +disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end, + GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb, + void *outcbarg, void *symcbarg) +{ + struct symtoken symtoken; + DisasmGetSymCB_t getsym = ctx->symcb ?: null_elf_getsym; + + if (ctx->elf != NULL) + { + /* Read all symbols of the ELF file and stuff them into a hash + table. The key is the address and the section index. */ + read_symtab (ctx); + + symtoken.ctx = ctx; + symtoken.symcbarg = symcbarg; + + symcbarg = &symtoken; + + getsym = default_elf_getsym; + } + + return ctx->ebl->disasm (startp, end, addr, fmt, outcb, getsym, outcbarg, + symcbarg); +} +INTDEF (disasm_cb) diff --git a/libasm/disasm_end.c b/libasm/disasm_end.c new file mode 100644 index 0000000..ee8b2f9 --- /dev/null +++ b/libasm/disasm_end.c @@ -0,0 +1,42 @@ +/* Release descriptor for disassembler. + Copyright (C) 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> + +#include "libasmP.h" + + +int +disasm_end (DisasmCtx_t *ctx) +{ + free (ctx); + + return 0; +} diff --git a/libasm/disasm_str.c b/libasm/disasm_str.c new file mode 100644 index 0000000..856fd11 --- /dev/null +++ b/libasm/disasm_str.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2007. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#include "libasmP.h" + + +struct buffer +{ + char *buf; + size_t len; +}; + + +static int +buffer_cb (char *str, size_t len, void *arg) +{ + struct buffer *buffer = (struct buffer *) arg; + + if (len > buffer->len) + /* Return additional needed space. */ + return len - buffer->len; + + buffer->buf = mempcpy (buffer->buf, str, len); + buffer->len = len; + + return 0; +} + + +int +disasm_str (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end, + GElf_Addr addr, const char *fmt, char **bufp, size_t len, + void *symcbarg) +{ + struct buffer buffer = { .buf = *bufp, .len = len }; + + int res = INTUSE(disasm_cb) (ctx, startp, end, addr, fmt, buffer_cb, &buffer, + symcbarg); + *bufp = buffer.buf; + return res; +} diff --git a/libasm/libasm.h b/libasm/libasm.h new file mode 100644 index 0000000..307c734 --- /dev/null +++ b/libasm/libasm.h @@ -0,0 +1,199 @@ +/* Interface for libasm. + Copyright (C) 2002, 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _LIBASM_H +#define _LIBASM_H 1 + +#include <stdbool.h> +#include <stdint.h> + +#include <libebl.h> + + +/* Opaque type for the assembler context descriptor. */ +typedef struct AsmCtx AsmCtx_t; + +/* Opaque type for a section. */ +typedef struct AsmScn AsmScn_t; + +/* Opaque type for a section group. */ +typedef struct AsmScnGrp AsmScnGrp_t; + +/* Opaque type for a symbol. */ +typedef struct AsmSym AsmSym_t; + + +/* Opaque type for the disassembler context descriptor. */ +typedef struct DisasmCtx DisasmCtx_t; + +/* Type used for callback functions to retrieve symbol name. The + symbol reference is in the section designated by the second parameter + at an offset described by the first parameter. The value is the + third parameter. */ +typedef int (*DisasmGetSymCB_t) (GElf_Addr, Elf32_Word, GElf_Addr, char **, + size_t *, void *); + +/* Output function callback. */ +typedef int (*DisasmOutputCB_t) (char *, size_t, void *); + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create output file and return descriptor for assembler context. If + TEXTP is true the output is an assembler format text file. + Otherwise an object file is created. The MACHINE parameter + corresponds to an EM_ constant from <elf.h>, KLASS specifies the + class (32- or 64-bit), and DATA specifies the byte order (little or + big endian). */ +extern AsmCtx_t *asm_begin (const char *fname, Ebl *ebl, bool textp); + +/* Abort the operation on the assembler context and free all resources. */ +extern int asm_abort (AsmCtx_t *ctx); + +/* Finalize output file and free all resources. */ +extern int asm_end (AsmCtx_t *ctx); + + +/* Return handle for the named section. If it was not used before + create it. */ +extern AsmScn_t *asm_newscn (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags); + + +/* Similar to 'asm_newscn', but make it part of section group GRP. */ +extern AsmScn_t *asm_newscn_ingrp (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags, + AsmScnGrp_t *grp); + +/* Create new subsection NR in the given section. */ +extern AsmScn_t *asm_newsubscn (AsmScn_t *asmscn, unsigned int nr); + + +/* Return handle for new section group. The signature symbol can be + set later. */ +extern AsmScnGrp_t *asm_newscngrp (AsmCtx_t *ctx, const char *grpname, + AsmSym_t *signature, Elf32_Word flags); + +/* Set or overwrite signature symbol for group. */ +extern int asm_scngrp_newsignature (AsmScnGrp_t *grp, AsmSym_t *signature); + + +/* Add zero terminated string STR of size LEN to (sub)section ASMSCN. */ +extern int asm_addstrz (AsmScn_t *asmscn, const char *str, size_t len); + +/* Add 8-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint8 (AsmScn_t *asmscn, int8_t num); + +/* Add 8-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint8 (AsmScn_t *asmscn, uint8_t num); + +/* Add 16-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint16 (AsmScn_t *asmscn, int16_t num); + +/* Add 16-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint16 (AsmScn_t *asmscn, uint16_t num); + +/* Add 32-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint32 (AsmScn_t *asmscn, int32_t num); + +/* Add 32-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint32 (AsmScn_t *asmscn, uint32_t num); + +/* Add 64-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint64 (AsmScn_t *asmscn, int64_t num); + +/* Add 64-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint64 (AsmScn_t *asmscn, uint64_t num); + + +/* Add signed little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_addsleb128 (AsmScn_t *asmscn, int32_t num); + +/* Add unsigned little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_adduleb128 (AsmScn_t *asmscn, uint32_t num); + + +/* Define new symbol NAME for current position in given section ASMSCN. */ +extern AsmSym_t *asm_newsym (AsmScn_t *asmscn, const char *name, + GElf_Xword size, int type, int binding); + + +/* Define new common symbol NAME with given SIZE and alignment. */ +extern AsmSym_t *asm_newcomsym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr align); + +/* Define new common symbol NAME with given SIZE, VALUE, TYPE, and BINDING. */ +extern AsmSym_t *asm_newabssym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr value, + int type, int binding); + + +/* Align (sub)section offset according to VALUE. */ +extern int asm_align (AsmScn_t *asmscn, GElf_Word value); + +/* Set the byte pattern used to fill gaps created by alignment. */ +extern int asm_fill (AsmScn_t *asmscn, void *bytes, size_t len); + + +/* Return ELF descriptor created for the output file of the given context. */ +extern Elf *asm_getelf (AsmCtx_t *ctx); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int asm_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *asm_errmsg (int __error); + + +/* Create context descriptor for disassembler. */ +extern DisasmCtx_t *disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb); + +/* Release descriptor for disassembler. */ +extern int disasm_end (DisasmCtx_t *ctx); + +/* Produce of disassembly output for given memory, store text in + provided buffer. */ +extern int disasm_str (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + char **bufp, size_t len, void *symcbarg); + +/* Produce disassembly output for given memory and output it using the + given callback functions. */ +extern int disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + DisasmOutputCB_t outcb, void *outcbarg, void *symcbarg); + +#ifdef __cplusplus +} +#endif + +#endif /* libasm.h */ diff --git a/libasm/libasm.map b/libasm/libasm.map new file mode 100644 index 0000000..a36cdbf --- /dev/null +++ b/libasm/libasm.map @@ -0,0 +1,38 @@ +ELFUTILS_1.0 { + global: + asm_abort; + asm_addint16; + asm_addint32; + asm_addint64; + asm_addint8; + asm_addsleb128; + asm_addstrz; + asm_adduint16; + asm_adduint32; + asm_adduint64; + asm_adduint8; + asm_adduleb128; + asm_align; + asm_begin; + asm_end; + asm_errmsg; + asm_errno; + asm_fill; + asm_getelf; + asm_newabssym; + asm_newcomsym; + asm_newscn; + asm_newscn_ingrp; + asm_newscngrp; + asm_newsubscn; + asm_newsym; + asm_scngrp_newsignature; + + disasm_begin; + disasm_cb; + disasm_end; + disasm_str; + + local: + *; +}; diff --git a/libasm/libasmP.h b/libasm/libasmP.h new file mode 100644 index 0000000..ee7005f --- /dev/null +++ b/libasm/libasmP.h @@ -0,0 +1,304 @@ +/* Internal definitions for libasm. + Copyright (C) 2002, 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _LIBASMP_H +#define _LIBASMP_H 1 + +#include <stdio.h> + +#include <libasm.h> + +/* gettext helper macros. */ +#define _(Str) dgettext ("elfutils", Str) + + +/* Known error codes. */ +enum + { + ASM_E_NOERROR, + ASM_E_NOMEM, /* No more memory. */ + ASM_E_CANNOT_CREATE, /* Output file cannot be created. */ + ASM_E_INVALID, /* Invalid parameters. */ + ASM_E_CANNOT_CHMOD, /* Cannot change mode of output file. */ + ASM_E_CANNOT_RENAME, /* Cannot rename output file. */ + ASM_E_DUPLSYM, /* Duplicate symbol definition. */ + ASM_E_LIBELF, /* Refer to error in libelf. */ + ASM_E_TYPE, /* Invalid section type for operation. */ + ASM_E_IOERROR, /* Error during output of data. */ + ASM_E_ENOSUP, /* No backend support. */ + ASM_E_NUM /* Keep this entry as the last. */ + }; + + +/* Special sections. */ +#define ASM_ABS_SCN ((Elf_Scn *) 1) +#define ASM_COM_SCN ((Elf_Scn *) 2) + + +/* And the hash table for symbols. */ +#include <symbolhash.h> + + +/* Descriptor for a section. */ +struct AsmScn +{ + /* The underlying assembler context. */ + AsmCtx_t *ctx; + + /* Subsection ID. */ + unsigned int subsection_id; + + /* Section type. */ + GElf_Word type; + + union + { + /* Data only stored in the record for subsection zero. */ + struct + { + /* The ELF section. */ + Elf_Scn *scn; + + /* Entry in the section header string table. */ + struct Ebl_Strent *strent; + + /* Next member of group. */ + struct AsmScn *next_in_group; + } main; + + /* Pointer to the record for subsection zero. */ + AsmScn_t *up; + } data; + + /* Current offset in the (sub)section. */ + GElf_Off offset; + /* Maximum alignment of the section so far. */ + GElf_Word max_align; + + /* Section content. */ + struct AsmData + { + /* Currently used number of bytes in the block. */ + size_t len; + + /* Number of bytes allocated. */ + size_t maxlen; + + /* Pointer to the next block. */ + struct AsmData *next; + + /* The actual data. */ + char data[flexarr_size]; + } *content; + + /* Fill pattern. */ + struct FillPattern + { + size_t len; + char bytes[flexarr_size]; + } *pattern; + + /* Next subsection. */ + AsmScn_t *subnext; + + /* List of all allocated sections. */ + AsmScn_t *allnext; + + /* Name of the section. */ + char name[flexarr_size]; +}; + + +/* Descriptor used for the assembling session. */ +struct AsmCtx +{ + /* File descriptor of the temporary file. */ + int fd; + + /* True if text output is wanted. */ + bool textp; + + /* Output file handle. */ + union + { + /* ELF descriptor of the temporary file. */ + Elf *elf; + /* I/O stream for text output. */ + FILE *file; + } out; + + + /* List with defined sections. */ + AsmScn_t *section_list; + /* Section header string table. */ + struct Ebl_Strtab *section_strtab; + + /* Table with defined symbols. */ + asm_symbol_tab symbol_tab; + /* Number of symbols in the table. */ + unsigned int nsymbol_tab; + /* Symbol string table. */ + struct Ebl_Strtab *symbol_strtab; + + /* List of section groups. */ + struct AsmScnGrp *groups; + /* Number of section groups. */ + size_t ngroups; + + /* Current required alignment for common symbols. */ + GElf_Word common_align; + + /* Lock to handle multithreaded programs. */ + rwlock_define (,lock); + + /* Counter for temporary symbols. */ + unsigned int tempsym_count; + + /* Name of the output file. */ + char *fname; + /* The name of the temporary file. */ + char tmp_fname[flexarr_size]; +}; + + +/* Descriptor for a symbol. */ +struct AsmSym +{ + /* Reference to the section which contains the symbol. */ + AsmScn_t *scn; + + /* Type of the symbol. */ + int8_t type; + /* Binding of the symbol. */ + int8_t binding; + + /* Size of the symbol. */ + GElf_Xword size; + + /* Offset in the section. */ + GElf_Off offset; + + /* Symbol table index of the symbol in the symbol table. */ + size_t symidx; + + /* Reference to name of the symbol. */ + struct Ebl_Strent *strent; +}; + + +/* Descriptor for section group. */ +struct AsmScnGrp +{ + /* Entry in the section header string table. */ + struct Ebl_Strent *strent; + + /* The ELF section. */ + Elf_Scn *scn; + + /* The signature. */ + struct AsmSym *signature; + + /* First member. */ + struct AsmScn *members; + /* Number of members. */ + size_t nmembers; + + /* Flags. */ + Elf32_Word flags; + + /* Next group. */ + struct AsmScnGrp *next; + + /* Name of the section group. */ + char name[flexarr_size]; +}; + + +/* Descriptor for disassembler. */ +struct DisasmCtx +{ + /* Handle for the backend library with the disassembler routine. */ + Ebl *ebl; + + /* ELF file containing all the data passed to the function. This + allows to look up symbols. */ + Elf *elf; + + /* Callback function to determine symbol names. */ + DisasmGetSymCB_t symcb; +}; + + +/* The default fill pattern: one zero byte. */ +extern const struct FillPattern *__libasm_default_pattern + attribute_hidden; + + +/* Ensure there are at least LEN bytes available in the output buffer + for ASMSCN. */ +extern int __libasm_ensure_section_space (AsmScn_t *asmscn, size_t len) + internal_function; + +/* Free all resources associated with the assembler context. */ +extern void __libasm_finictx (AsmCtx_t *ctx) internal_function; + +/* Set error code. */ +extern void __libasm_seterrno (int err) internal_function; + +/* Return handle for the named section. If it was not used before + create it. */ +extern AsmScn_t *__asm_newscn_internal (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags) + attribute_hidden; + + +/* Internal aliases of the asm_addintXX functions. */ +extern int __asm_addint8_internal (AsmScn_t *asmscn, int8_t num) + attribute_hidden; +extern int __asm_addint16_internal (AsmScn_t *asmscn, int16_t num) + attribute_hidden; +extern int __asm_addint32_internal (AsmScn_t *asmscn, int32_t num) + attribute_hidden; +extern int __asm_addint64_internal (AsmScn_t *asmscn, int64_t num) + attribute_hidden; + + +/* Produce disassembly output for given memory and output it using the + given callback functions. */ +extern int __disasm_cb_internal (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, + const char *fmt, DisasmOutputCB_t outcb, + void *outcbarp, void *symcbarg) + attribute_hidden; + + +/* Test whether given symbol is an internal symbol and if yes, whether + we should nevertheless emit it in the symbol table. */ +// XXX The second part should probably be controlled by an option which +// isn't implemented yet +// XXX Also, the format will change with the backend. +#define asm_emit_symbol_p(name) (strncmp (name, ".L", 2) != 0) + +#endif /* libasmP.h */ diff --git a/libasm/symbolhash.c b/libasm/symbolhash.c new file mode 100644 index 0000000..e3aa5dd --- /dev/null +++ b/libasm/symbolhash.c @@ -0,0 +1,51 @@ +/* Symbol hash table implementation. + Copyright (C) 2001, 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2001. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#include <libasmP.h> +#include <libebl.h> + +/* Definitions for the symbol hash table. */ +#define TYPE AsmSym_t * +#define NAME asm_symbol_tab +#define ITERATE 1 +#define REVERSE 1 +#define COMPARE(a, b) \ + strcmp (ebl_string ((a)->strent), ebl_string ((b)->strent)) + +#define next_prime __libasm_next_prime +extern size_t next_prime (size_t) attribute_hidden; + +#include "../lib/dynamicsizehash.c" + +#undef next_prime +#define next_prime attribute_hidden __libasm_next_prime +#include "../lib/next_prime.c" diff --git a/libasm/symbolhash.h b/libasm/symbolhash.h new file mode 100644 index 0000000..28768da --- /dev/null +++ b/libasm/symbolhash.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2001, 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2001. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef SYMBOLHASH_H +#define SYMBOLHASH_H 1 + +/* Definitions for the symbol hash table. */ +#define TYPE AsmSym_t * +#define NAME asm_symbol_tab +#define ITERATE 1 +#define COMPARE(a, b) \ + strcmp (ebl_string ((a)->strent), ebl_string ((b)->strent)) +#include <dynamicsizehash.h> + +#endif /* symbolhash.h */ |