summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIliyan Malchev <malchev@google.com>2011-03-08 16:19:48 -0800
committerIliyan Malchev <malchev@google.com>2011-03-12 14:59:46 -0800
commitb375e71d306f2fd356b9b356b636e568c4581fa1 (patch)
tree0cb0325afabe55732edb092659793d39d51c4212
parent0469678719a5e8d59b779c8ae8e87a317c5788f5 (diff)
downloadbuild-b375e71d306f2fd356b9b356b636e568c4581fa1.zip
build-b375e71d306f2fd356b9b356b636e568c4581fa1.tar.gz
build-b375e71d306f2fd356b9b356b636e568c4581fa1.tar.bz2
build: remove prelinker build build system
This patch removes support for prelinking from the build system. By now, the prelinker has outlived its usefulness for several reasons. Firstly, the speedup that it afforded in the early days of Android is now nullified by the speed of hardware, as well as by the presence of Zygote. Secondly, the space savings that come with prelinking (measued at 17MB on a recent honeycomb stingray build) are no longer important either. Thirdly, prelinking reduces the effectiveness of Address-Space-Layout Randomization. Finally, since it is not part of the gcc suite, the prelinker needs to be maintained separately. The patch deletes apriori, soslim, lsd, isprelinked, and iself from the source tree. It also removes the prelink map. LOCAL_PRELINK_MODULE becomes a no-op. Individual Android.mk will get cleaned separately. Support for prelinking will have to be removed from the recovery code and from the dynamic loader as well. Change-Id: I5839c9c25f7772d5183eedfe20ab924f2a7cd411
-rw-r--r--CleanSpec.mk9
-rw-r--r--core/clear_vars.mk1
-rw-r--r--core/combo/TARGET_linux-arm.mk4
-rw-r--r--core/combo/select.mk2
-rw-r--r--core/config.mk7
-rw-r--r--core/definitions.mk13
-rw-r--r--core/dynamic_binary.mk43
-rw-r--r--core/executable.mk5
-rw-r--r--core/main.mk4
-rw-r--r--core/prelink-linux-arm.map218
-rw-r--r--core/product.mk1
-rw-r--r--core/shared_library.mk3
-rw-r--r--core/user_tags.mk5
-rw-r--r--target/board/generic_x86/BoardConfig.mk1
-rw-r--r--target/board/sim/BoardConfig.mk6
-rw-r--r--target/board/vbox_x86/BoardConfig.mk1
-rw-r--r--tools/apriori/Android.mk61
-rw-r--r--tools/apriori/apriori.c2775
-rw-r--r--tools/apriori/apriori.h14
-rw-r--r--tools/apriori/cmdline.c186
-rw-r--r--tools/apriori/cmdline.h21
-rw-r--r--tools/apriori/common.h28
-rw-r--r--tools/apriori/debug.c38
-rw-r--r--tools/apriori/debug.h88
-rw-r--r--tools/apriori/hash.c27
-rw-r--r--tools/apriori/hash.h14
-rw-r--r--tools/apriori/main.c229
-rw-r--r--tools/apriori/prelink_info.c106
-rw-r--r--tools/apriori/prelink_info.h9
-rw-r--r--tools/apriori/prelinkmap.c170
-rw-r--r--tools/apriori/prelinkmap.h10
-rw-r--r--tools/apriori/rangesort.c317
-rw-r--r--tools/apriori/rangesort.h105
-rw-r--r--tools/apriori/source.c18
-rw-r--r--tools/apriori/source.h122
-rwxr-xr-xtools/apriori/tweak.h15
-rwxr-xr-xtools/iself/Android.mk23
-rw-r--r--tools/iself/debug.h90
-rw-r--r--tools/iself/iself.c36
-rwxr-xr-xtools/isprelinked/Android.mk40
-rw-r--r--tools/isprelinked/common.h28
-rw-r--r--tools/isprelinked/debug.c37
-rw-r--r--tools/isprelinked/debug.h88
-rw-r--r--tools/isprelinked/isprelinked.c89
-rw-r--r--tools/isprelinked/prelink_info.c71
-rw-r--r--tools/isprelinked/prelink_info.h8
-rw-r--r--tools/lsd/Android.mk43
-rw-r--r--tools/lsd/cmdline.c130
-rw-r--r--tools/lsd/cmdline.h13
-rw-r--r--tools/lsd/common.h12
-rw-r--r--tools/lsd/debug.c39
-rw-r--r--tools/lsd/debug.h93
-rw-r--r--tools/lsd/hash.c29
-rw-r--r--tools/lsd/hash.h14
-rw-r--r--tools/lsd/lsd.c777
-rw-r--r--tools/lsd/lsd.h10
-rw-r--r--tools/lsd/main.c67
-rw-r--r--tools/soslim/Android.mk49
-rw-r--r--tools/soslim/cmdline.c141
-rw-r--r--tools/soslim/cmdline.h16
-rw-r--r--tools/soslim/common.c35
-rw-r--r--tools/soslim/common.h49
-rw-r--r--tools/soslim/debug.c40
-rw-r--r--tools/soslim/debug.h88
-rw-r--r--tools/soslim/main.c374
-rw-r--r--tools/soslim/prelink_info.c204
-rw-r--r--tools/soslim/prelink_info.h13
-rw-r--r--tools/soslim/soslim.c536
-rw-r--r--tools/soslim/soslim.h35
-rw-r--r--tools/soslim/symfilter.c246
-rw-r--r--tools/soslim/symfilter.h50
71 files changed, 16 insertions, 8273 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5002de8..c49f26c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -72,6 +72,15 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/*.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/*.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/*.so)
+$(call add-clean-step, rm -rf $(HOST_OUT_EXECUTABLES)/iself)
+$(call add-clean-step, rm -rf $(HOST_OUT_EXECUTABLES)/lsd)
+$(call add-clean-step, rm -rf $(HOST_OUT_EXECUTABLES)/apriori)
+$(call add-clean-step, rm -rf $(HOST_OUT_EXECUTABLES)/isprelinked)
+$(call add-clean-step, rm -rf $(HOST_OUT_EXECUTABLES)/soslim)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index f947bf6..bc6ed0c 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -75,7 +75,6 @@ LOCAL_COPY_HEADERS_TO:=
LOCAL_COPY_HEADERS:=
LOCAL_FORCE_STATIC_EXECUTABLE:=
LOCAL_ADDITIONAL_DEPENDENCIES:=
-LOCAL_PRELINK_MODULE:=
LOCAL_COMPRESS_MODULE_SYMBOLS:=
LOCAL_STRIP_MODULE:=
LOCAL_POST_PROCESS_COMMAND:=true
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 3a3a5bd..46e0f75 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -52,8 +52,8 @@ TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-TARGET_STRIP := $(HOST_OUT_EXECUTABLES)/soslim$(HOST_EXECUTABLE_SUFFIX)
-TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip --shady --quiet $< --outfile $@
+TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip-debug $< -o $@
TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
diff --git a/core/combo/select.mk b/core/combo/select.mk
index c886342..86157d1 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -56,8 +56,6 @@ $(combo_target)SHLIB_SUFFIX := .so
$(combo_target)JNILIB_SUFFIX := $($(combo_target)SHLIB_SUFFIX)
$(combo_target)STATIC_LIB_SUFFIX := .a
-$(combo_target)PRELINKER_MAP := $(BUILD_SYSTEM)/prelink-$(combo_os_arch).map
-
# Now include the combo for this specific target.
include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk
diff --git a/core/config.mk b/core/config.mk
index c6f6288..3b0e92e 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -105,9 +105,6 @@ TARGET_ERROR_FLAGS := -Werror=return-type -Werror=non-virtual-dtor -Werror=addre
# TODO: do symbol compression
TARGET_COMPRESS_MODULE_SYMBOLS := false
-# Default is to prelink modules.
-TARGET_PRELINK_MODULE := true
-
# Default shell is ash. Other possible value is mksh.
TARGET_SHELL := ash
@@ -236,10 +233,6 @@ FINDBUGS := prebuilt/common/findbugs/bin/findbugs
LOCALIZE := $(HOST_OUT_EXECUTABLES)/localize$(HOST_EXECUTABLE_SUFFIX)
EMMA_JAR := external/emma/lib/emma$(COMMON_JAVA_PACKAGE_SUFFIX)
-# Binary prelinker/compressor tools
-APRIORI := $(HOST_OUT_EXECUTABLES)/apriori$(HOST_EXECUTABLE_SUFFIX)
-LSD := $(HOST_OUT_EXECUTABLES)/lsd$(HOST_EXECUTABLE_SUFFIX)
-
# Deal with archaic version of bison on Mac OS X.
ifeq ($(filter 1.28,$(shell $(YACC) -V)),)
YACC_HEADER_SUFFIX:= .hpp
diff --git a/core/definitions.mk b/core/definitions.mk
index 6db9d8f..1202362 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -66,7 +66,7 @@ ALL_GENERATED_SOURCES:=
# These all have an order-only dependency on the copied headers
ALL_C_CPP_ETC_OBJECTS:=
-# The list of dynamic binaries that haven't been stripped/compressed/prelinked.
+# The list of dynamic binaries that haven't been stripped/compressed/etc.
ALL_ORIGINAL_DYNAMIC_BINARIES:=
# These files go into the SDK
@@ -1221,17 +1221,6 @@ define transform-to-stripped
$(hide) $(TARGET_STRIP_COMMAND)
endef
-define transform-to-prelinked
-@mkdir -p $(dir $@)
-@echo "target Prelink: $(PRIVATE_MODULE) ($@)"
-$(hide) $(APRIORI) \
- --prelinkmap $(TARGET_PRELINKER_MAP) \
- --locals-only \
- --quiet \
- $< \
- --output $@
-endef
-
###########################################################
## Commands for running gcc to link an executable
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 005ccf3..437361a 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -88,47 +88,9 @@ endif
###########################################################
-## Pre-link
-###########################################################
-prelink_input := $(compress_output)
-# The output of the prelink step is the binary we want to use
-# for symbolic debugging; the prelink step may move sections
-# around, so we have to use this version.
-prelink_output := $(LOCAL_UNSTRIPPED_PATH)/$(LOCAL_BUILT_MODULE_STEM)
-
-# Skip prelinker if it is FDO instrumentation build.
-ifneq ($(strip $(BUILD_FDO_INSTRUMENT)),)
-ifneq ($(LOCAL_NO_FDO_SUPPORT),true)
-LOCAL_PRELINK_MODULE := false
-endif
-endif
-
-ifeq ($(LOCAL_PRELINK_MODULE),true)
-$(prelink_output): $(prelink_input) $(TARGET_PRELINKER_MAP) $(APRIORI)
- $(transform-to-prelinked)
-else
-# Don't prelink the binary, just copy it. We can't skip this step
-# because people always expect a copy of the binary to appear
-# in the UNSTRIPPED directory.
-#
-# If the binary we're copying is acp or a prerequisite,
-# use cp(1) instead.
-ifneq ($(LOCAL_ACP_UNAVAILABLE),true)
-$(prelink_output): $(prelink_input) | $(ACP)
- @echo "target Non-prelinked: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-target)
-else
-$(prelink_output): $(prelink_input)
- @echo "target Non-prelinked: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-target-with-cp)
-endif
-endif
-
-
-###########################################################
## Strip
###########################################################
-strip_input := $(prelink_output)
+strip_input := $(compress_output)
strip_output := $(LOCAL_BUILT_MODULE)
ifeq ($(strip $(LOCAL_STRIP_MODULE)),)
@@ -160,5 +122,4 @@ endif # LOCAL_STRIP_MODULE
$(cleantarget): PRIVATE_CLEAN_FILES := \
$(PRIVATE_CLEAN_FILES) \
$(linked_module) \
- $(compress_output) \
- $(prelink_output)
+ $(compress_output)
diff --git a/core/executable.mk b/core/executable.mk
index 623c766..6138adb 100644
--- a/core/executable.mk
+++ b/core/executable.mk
@@ -12,11 +12,6 @@ ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),)
LOCAL_MODULE_SUFFIX := $(TARGET_EXECUTABLE_SUFFIX)
endif
-# Executables are not prelinked. If we decide to start prelinking
-# them, the LOCAL_PRELINK_MODULE definitions should be moved from
-# here and shared_library.make and consolidated in dynamic_binary.make.
-LOCAL_PRELINK_MODULE := false
-
include $(BUILD_SYSTEM)/dynamic_binary.mk
ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
diff --git a/core/main.mk b/core/main.mk
index a5ee6d1..1a30f16 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -479,10 +479,6 @@ subdirs := \
build/libs \
build/target \
build/tools/acp \
- build/tools/apriori \
- build/tools/soslim \
- external/elfcopy \
- external/elfutils \
external/yaffs2 \
external/zlib
else # !BUILD_TINY_ANDROID
diff --git a/core/prelink-linux-arm.map b/core/prelink-linux-arm.map
deleted file mode 100644
index 41cd8cd..0000000
--- a/core/prelink-linux-arm.map
+++ /dev/null
@@ -1,218 +0,0 @@
-# 0xC0000000 - 0xFFFFFFFF Kernel
-# 0xB0100000 - 0xBFFFFFFF Thread 0 Stack
-# 0xB0000000 - 0xB00FFFFF Linker
-# 0xA0000000 - 0xBFFFFFFF Prelinked System Libraries
-# 0x90000000 - 0x9FFFFFFF Prelinked App Libraries
-# 0x80000000 - 0x8FFFFFFF Non-prelinked Libraries
-# 0x40000000 - 0x7FFFFFFF mmap'd stuff
-# 0x10000000 - 0x3FFFFFFF Thread Stacks
-# 0x00000000 - 0x0FFFFFFF .text / .data / heap
-
-# Note: The general rule is that libraries should be aligned on 1MB
-# boundaries. For ease of updating this file, you will find a comment
-# on each line, indicating the observed size of the library, which is
-# one of:
-#
-# [<64K] observed to be less than 64K
-# [~1M] rounded up, one megabyte (similarly for other sizes)
-# [???] no size observed, assumed to be one megabyte
-#
-# note: look at the LOAD sections in the library header:
-#
-# arm-linux-androideabi-objdump -x <lib>
-#
-
-# core system libraries
-libdl.so 0xB0100000 # [<64K]
-libc.so 0xAFF00000 # [~2M]
-libstdc++.so 0xAFE00000 # [<64K]
-libm.so 0xAFD00000 # [~1M]
-liblog.so 0xAFC00000 # [<64K]
-libcutils.so 0xAFB00000 # [~1M]
-libthread_db.so 0xAFA00000 # [<64K]
-libz.so 0xAF900000 # [~1M]
-libevent.so 0xAF800000 # [???]
-libssl.so 0xAF600000 # [~2M]
-libcrypto.so 0xAF200000 # [~4M]
-libsysutils.so 0xAF100000 # [~1M]
-
-# bluetooth
-liba2dp.so 0xAF000000 # [~1M]
-input.so 0xAEF00000 # [~1M]
-audio.so 0xAEE00000 # [~1M]
-libglib.so 0xAED00000 # [~1M]
-network.so 0xAEC00000 # [~1M]
-libbluetoothd.so 0xAEA00000 # [~2M]
-libbluedroid.so 0xAE900000 # [<64K]
-libbluetooth.so 0xAE800000 # [~1M]
-libdbus.so 0xAE700000 # [~1M]
-
-# extended system libraries
-libril.so 0xAE600000 # [~1M]
-libreference-ril.so 0xAE500000 # [~1M]
-libwpa_client.so 0xAE400000 # [<64K]
-libnetutils.so 0xAE300000 # [~1M]
-
-# core dalvik runtime support
-libandroid_servers.so 0xAE200000 # [~1M]
-libicuuc.so 0xADE00000 # [~4M]
-libicui18n.so 0xAD900000 # [~5M]
-libandroid_runtime.so 0xAD300000 # [~6M]
-libnativehelper.so 0xAD100000 # [~2M]
-libdvm-ARM.so 0xAD000000 # [???]
-libdvm.so 0xACA00000 # [~6M]
-# Note: libicudata.so intentionally omitted
-
-# graphics
-libpixelflinger.so 0xAC900000 # [~1M]
-# libcorecg is for backward-compatibility with donut
-libcorecg.so 0xAC800000 # [???]
-libsurfaceflinger_client.so 0xAC700000 # [~1M]
-libsurfaceflinger.so 0xAC500000 # [~2M]
-libGLES_android.so 0xAC400000 # [~1M]
-libagl.so 0xAC300000 # [???]
-
-libGLESv1_CM.so 0xAC200000 # [~1M]
-libGLESv2.so 0xAC100000 # [~1M]
-libOpenVG_CM.so 0xAC000000 # [???]
-libOpenVGU_CM.so 0xABF00000 # [???]
-libEGL.so 0xABE00000 # [~1M]
-libETC1.so 0xABD00000 # [<64K]
-
-libacc.so 0xABC00000 # [~1M]
-
-libexif.so 0xABB00000 # [~1M]
-libcamera_client.so 0xABA80000 # [~1M]
-libui.so 0xAB900000 # [~1M]
-libgui.so 0xAB800000 # [~1M]
-libskia.so 0xAB100000 # [~2M]
-librs_jni.so 0xAB000000 # [~1M]
-libRS.so 0xA9E00000 # [~2M]
-libandroid.so 0xA9D80000 # [<64K]
-libjnigraphics.so 0xA9D00000 # [<64K]
-libskiagl.so 0xA9C00000 # [~1M]
-
-# audio
-libaudiopolicy.so 0xA9A00000 # [~1M]
-libeffects.so 0xA9980000 # [<64K]
-libaudioeffect_jni.so 0xA9900000 # [<64K]
-libsoundpool.so 0xA9800000 # [~1M]
-libaudio.so 0xA9700000 # [~1M]
-libspeech.so 0xA9600000 # [~1M]
-libsonivox.so 0xA9500000 # [~1M]
-libvorbisidec.so 0xA9400000 # [~1M]
-libmedia_jni.so 0xA9300000 # [~1M]
-libmediaplayerservice.so 0xA9200000 # [~1M]
-libmedia.so 0xA9000000 # [~2M]
-libFFTEm.so 0xA8F00000 # [~1M]
-libSR_AudioIn.so 0xA8E00000 # [~1M] for external/srec
-libaudioflinger.so 0xA8D00000 # [~1M]
-
-# assorted system libraries
-libsqlite.so 0xA8B00000 # [~2M]
-libexpat.so 0xA8A00000 # [~1M]
-libwebcore.so 0xA8200000 # [~8M]
-libbinder.so 0xA8100000 # [~1M]
-libutils.so 0xA8000000 # [~1M]
-libcameraservice.so 0xA7F00000 # [~1M]
-libhardware.so 0xA7E00000 # [<64K]
-libhardware_legacy.so 0xA7D00000 # [~1M]
-libapp_process.so 0xA7C00000 # [???]
-libsystem_server.so 0xA7B00000 # [~1M]
-libime.so 0xA7A00000 # [???]
-libgps.so 0xA7900000 # [~1M]
-libcamera.so 0xA7800000 # [~1M]
-liboemcamera.so 0xA7600000 # [~2M]
-libdiskconfig.so 0xA7500000 # [<64K]
-libemoji.so 0xA7400000 # [<64K]
-libjni_latinime.so 0xA7300000 # [~1M]
-libjni_pinyinime.so 0xA7200000 # [~1M]
-libttssynthproxy.so 0xA7100000 # [~1M] for frameworks/base
-libttspico.so 0xA6F00000 # [~2M] for external/svox
-libmtp.so 0xA6E00000 # [~1M]
-libusbhost.so 0xA6D00000 # [<64K]
-libinput.so 0xA6C00000 # [~1M]
-
-# pv libraries
-libpvasf.so 0xA6B00000 # [???]
-libpvasfreg.so 0xA6A00000 # [???]
-libomx_sharedlibrary.so 0xA6900000 # [~1M]
-libopencore_download.so 0xA6800000 # [~1M]
-libopencore_downloadreg.so 0xA6700000 # [~1M]
-libopencore_net_support.so 0xA6400000 # [~3M]
-libopencore_rtsp.so 0xA5E00000 # [~6M]
-libopencore_rtspreg.so 0xA5D00000 # [~1M]
-libopencore_author.so 0xA5900000 # [~4M]
-libomx_aacdec_sharedlibrary.so 0xA5700000 # [~2M]
-libomx_amrdec_sharedlibrary.so 0xA5600000 # [~1M]
-libomx_amrenc_sharedlibrary.so 0xA5500000 # [~1M]
-libomx_avcdec_sharedlibrary.so 0xA5400000 # [~1M]
-libomx_avcenc_sharedlibrary.so 0xA5300000 # [???]
-libomx_m4vdec_sharedlibrary.so 0xA5200000 # [~1M]
-libomx_m4venc_sharedlibrary.so 0xA5100000 # [???]
-libomx_mp3dec_sharedlibrary.so 0xA5000000 # [~1M]
-libopencore_mp4local.so 0xA4E00000 # [~2M]
-libopencore_mp4localreg.so 0xA4D00000 # [~1M]
-libopencore_player.so 0xA4400000 # [~9M]
-
-# opencore hardware support
-libmm-adspsvc.so 0xA4300000 # [<64K]
-libOmxCore.so 0xA4200000 # [<64K]
-libOmxMpeg4Dec.so 0xA4100000 # [~1M]
-libOmxH264Dec.so 0xA4000000 # [~1M]
-libOmxVidEnc.so 0xA3F00000 # [~1M]
-libopencorehw.so 0xA3E00000 # [~1M]
-libOmxVdec.so 0xA3D00000 # [~1M]
-libmm-omxcore.so 0xA3C00000 # [<64K]
-
-# pv libraries
-libopencore_common.so 0xA3500000 # [~7M]
-libqcomm_omx.so 0xA3400000 # [<64K]
-
-# stagefright libraries
-libstagefright_amrnb_common.so 0xA3300000 # [~1M]
-libstagefright_avc_common.so 0xA3200000 # [~1M]
-libstagefright_color_conversion.so 0xA3100000 # [<64K]
-libstagefright_omx.so 0xA3000000 # [~1M]
-libstagefrighthw.so 0xA2F00000 # [~1M]
-libstagefright.so 0xA2B00000 # [~4M]
-
-# libraries for specific hardware
-libgsl.so 0xA2A00000 # [~1M]
-libhtc_acoustic.so 0xA2900000 # [<64K]
-libhtc_ril.so 0xA2800000 # [~1M]
-libreference-cdma-sms.so 0xA2600000 # [<64K] for hardware/ril
-
-# libraries for specific apps or temporary libraries
-libcam_ipl.so 0x9F000000 # [???]
-libwbxml.so 0x9EF00000 # [???]
-libwbxml_jni.so 0x9EE00000 # [~1M]
-libxml2wbxml.so 0x9EB00000 # [~1M]
-libdrm1.so 0x9EA00000 # [~1M]
-libdrm1_jni.so 0x9E900000 # [<64K]
-libwapcore.so 0x9E800000 # [???]
-libstreetview.so 0x9E700000 # [???]
-libwapbrowsertest.so 0x9E600000 # [???]
-libminiglobe.so 0x9E500000 # [???]
-libearth.so 0x9E400000 # [???]
-libembunit.so 0x9E300000 # [<64K]
-libneon.so 0x9E200000 # [???]
-libjni_example.so 0x9E100000 # [???]
-libjni_load_test.so 0x9E000000 # [???]
-libjni_lib_test.so 0x9DF00000 # [???]
-librunperf.so 0x9DE00000 # [???]
-libctest.so 0x9DD00000 # [<64K]
-libUAPI_jni.so 0x9DC00000 # [???]
-librpc.so 0x9DB00000 # [~1M]
-libtrace_test.so 0x9DA00000 # [???]
-libsrec_jni.so 0x9D800000 # [~2M]
-libjpeg.so 0x9D700000 # [~1M]
-libiprouteutil.so 0x9D600000 # [~1M] for external/iproute2
-libnetlink.so 0x9D500000 # [<64K] for external/iproute2
-libpagemap.so 0x9D400000 # [<64K] for system/extras/libpagemap
-libstlport.so 0x9D100000 # [~3M] for external/stlport
-libzxing.so 0x9D000000 # [<64K] for goggles
-libinterstitial.so 0x9CF00000 # [<64K] for goggles
-liblept.so 0x9CA00000 # [~5M] for external/leptonica
-libbcc.so 0x9C600000 # [~4M] for external/llvm
-libchromium_net.so 0x9C400000 # [~2M] for exteral/webkit
diff --git a/core/product.mk b/core/product.mk
index 249582b..cc62e10 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -196,7 +196,6 @@ _product_stash_var_list := $(_product_var_list) \
TARGET_BOARD_PLATFORM_GPU \
TARGET_BOOTLOADER_BOARD_NAME \
TARGET_COMPRESS_MODULE_SYMBOLS \
- TARGET_PRELINK_MODULE \
TARGET_NO_BOOTLOADER \
TARGET_NO_KERNEL \
TARGET_NO_RECOVERY \
diff --git a/core/shared_library.mk b/core/shared_library.mk
index 940fe61..47a089a 100644
--- a/core/shared_library.mk
+++ b/core/shared_library.mk
@@ -13,9 +13,6 @@ endif
ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),)
LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX)
endif
-ifeq ($(strip $(LOCAL_PRELINK_MODULE)),)
-LOCAL_PRELINK_MODULE := $(strip $(TARGET_PRELINK_MODULE))
-endif
ifneq ($(strip $(OVERRIDE_BUILT_MODULE_PATH)),)
$(error $(LOCAL_PATH): Illegal use of OVERRIDE_BUILT_MODULE_PATH)
endif
diff --git a/core/user_tags.mk b/core/user_tags.mk
index 090b7fa..d30e86b 100644
--- a/core/user_tags.mk
+++ b/core/user_tags.mk
@@ -49,7 +49,6 @@ GRANDFATHERED_USER_MODULES += \
apkcheck \
applypatch \
app_process \
- apriori \
archquery \
asm-3.1 \
atree \
@@ -155,8 +154,6 @@ GRANDFATHERED_USER_MODULES += \
input \
ip \
iptables \
- iself \
- isprelinked \
jarjar \
javax.obex \
jcommon-1.0.12 \
@@ -221,7 +218,6 @@ GRANDFATHERED_USER_MODULES += \
libeffects \
libEGL \
libelf \
- libelfcopy \
libESR_Portable \
libESR_Shared \
libETC1 \
@@ -481,7 +477,6 @@ GRANDFATHERED_USER_MODULES += \
signature-tools \
simg2img \
simulator \
- soslim \
spec-progress \
sqlite3 \
stack_dump \
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 83a8c3e..0b98e2a 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -1,7 +1,6 @@
TARGET_ARCH=x86
DISABLE_DEXPREOPT := true
TARGET_COMPRESS_MODULE_SYMBOLS := false
-TARGET_PRELINK_MODULE := false
TARGET_NO_RECOVERY := true
TARGET_HARDWARE_3D := false
BOARD_USES_GENERIC_AUDIO := true
diff --git a/target/board/sim/BoardConfig.mk b/target/board/sim/BoardConfig.mk
index ba25c18..ba55b92 100644
--- a/target/board/sim/BoardConfig.mk
+++ b/target/board/sim/BoardConfig.mk
@@ -3,13 +3,11 @@
# Product-specific compile-time definitions.
#
-# Don't try prelinking or compressing the shared libraries
-# used by the simulator. The host OS won't know what to do
-# with them, and they may not even be ELF files.
+# Don't try compressing the shared libraries used by the simulator. The host
+# OS won't know what to do with them, and they may not even be ELF files.
#
# These definitions override the defaults in config/config.make.
TARGET_COMPRESS_MODULE_SYMBOLS := false
-TARGET_PRELINK_MODULE := false
# Don't try to build a bootloader.
TARGET_NO_BOOTLOADER := true
diff --git a/target/board/vbox_x86/BoardConfig.mk b/target/board/vbox_x86/BoardConfig.mk
index 525074e..2bdcced 100644
--- a/target/board/vbox_x86/BoardConfig.mk
+++ b/target/board/vbox_x86/BoardConfig.mk
@@ -5,7 +5,6 @@
TARGET_ARCH=x86
DISABLE_DEXPREOPT := true
TARGET_COMPRESS_MODULE_SYMBOLS := false
-TARGET_PRELINK_MODULE := false
TARGET_NO_RECOVERY := true
TARGET_HARDWARE_3D := false
BOARD_USES_GENERIC_AUDIO := true
diff --git a/tools/apriori/Android.mk b/tools/apriori/Android.mk
deleted file mode 100644
index 79ecf7f..0000000
--- a/tools/apriori/Android.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for apriori
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-ifneq ($(TARGET_SIMULATOR),true)
-include $(CLEAR_VARS)
-
-LOCAL_LDLIBS += -ldl
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS
-LOCAL_CFLAGS += -DDEBUG
-LOCAL_CFLAGS += -DADJUST_ELF=1
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
-LOCAL_CFLAGS += -DBIG_ENDIAN=1
-endif
-
-ifeq ($(HOST_OS),darwin)
-LOCAL_CFLAGS += -DFSCANF_IS_BROKEN
-endif
-ifeq ($(HOST_OS),windows)
-LOCAL_CFLAGS += -DFSCANF_IS_BROKEN
-LOCAL_LDLIBS += -lintl
-endif
-
-
-
-LOCAL_SRC_FILES := \
- apriori.c \
- cmdline.c \
- debug.c \
- hash.c \
- main.c \
- prelink_info.c \
- rangesort.c \
- source.c \
- prelinkmap.c
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/ \
- external/elfutils/lib/ \
- external/elfutils/libelf/ \
- external/elfutils/libebl/ \
- external/elfcopy/
-
-LOCAL_STATIC_LIBRARIES := libelfcopy libelf libebl #dl
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_STATIC_LIBRARIES += libebl_arm
-endif
-
-LOCAL_MODULE := apriori
-
-include $(BUILD_HOST_EXECUTABLE)
-endif # TARGET_SIMULATOR != true
diff --git a/tools/apriori/apriori.c b/tools/apriori/apriori.c
deleted file mode 100644
index b827375..0000000
--- a/tools/apriori/apriori.c
+++ /dev/null
@@ -1,2775 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <libebl.h>
-#ifdef ARM_SPECIFIC_HACKS
- #include <libebl_arm.h>
-#endif/*ARM_SPECIFIC_HACKS*/
-#include <elf.h>
-#include <gelf.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <hash.h>
-#include <apriori.h>
-#include <source.h>
-#include <tweak.h>
-#include <rangesort.h>
-#include <prelink_info.h>
-#include <prelinkmap.h>
-#include <libgen.h>
-
-#ifndef ADJUST_ELF
-#error "ADJUST_ELF must be defined!"
-#endif
-
-/* When this macro is defined, apriori sets to ZERO those relocation values for
- which it canot find the appropriate referent.
-*/
-#define PERMISSIVE
-#define COPY_SECTION_DATA_BUFFER (0)
-/* When this macro is set to a nonzero value, we replace calls to elf_strptr()
- on the target ELF handle with code that extracts the strings directly from
- the data buffers of that ELF handle. In this case, elf_strptr() does not
- work as expected, as it tries to read the data buffer of the associated
- string section directly from the file, and that buffer does not exist yet
- in the file, since we haven't committed our changes yet.
-*/
-#define ELF_STRPTR_IS_BROKEN (1)
-
-/* When the macro below is defined, apriori does not mark for removal those
- relocation sections that it fully handles. Instead, apriori just sets their
- sizes to zero. This is more for debugging than of any actual use.
-
- This macro is meaningful only when ADJUST_ELF!=0
-*/
-#define REMOVE_HANDLED_SECTIONS
-
-extern int verbose_flag;
-
-static source_t *sources = NULL;
-
-/* Retouch data is a very concise representation of the resolved relocations.
- This data is used to randomize the location of prelinked libraries at
- update time, on the device.
- */
-
-// We will store retouch entries into this buffer, then dump them at the
-// end of the .so file before setup_prelink_info().
-#define RETOUCH_MAX_SIZE 600000
-static char *retouch_buf;
-static unsigned int retouch_byte_cnt;
-// Compression state.
-static int32_t offs_prev;
-static uint32_t cont_prev;
-
-#define false 0
-#define true 1
-
-void retouch_init(void) {
- offs_prev = 0;
- cont_prev = 0;
- retouch_byte_cnt = 0;
- retouch_buf = malloc(RETOUCH_MAX_SIZE+12);
- FAILIF(retouch_buf == NULL,
- "Could not allocate %d bytes.\n", RETOUCH_MAX_SIZE+12);
-}
-
-//
-// We use three encoding schemes; this takes care of much of the redundancy
-// inherent in lists of relocations:
-//
-// * two bytes, leading 1, 2b for d_offset ("s"), 13b for d_contents ("c")
-//
-// 76543210 76543210
-// 1ssccccc cccccccc
-//
-// * three bytes, leading 01, 2b for delta offset, 20b for delta contents
-//
-// 76543210 76543210 76543210
-// 01sscccc cccccccc cccccccc
-//
-// * eigth bytes, leading 00, 30b for offset, 32b for contents
-//
-// 76543210 76543210 76543210 76543210
-// 00ssssss ssssssss ssssssss ssssssss + 4 bytes contents
-//
-// NOTE 1: All deltas are w.r.t. the previous line in the list.
-// NOTE 2: Two-bit ("ss") offsets mean: "00"=4, "01"=8, "10"=12, and "11"=16.
-// NOTE 3: Delta contents are signed. To map back to a int32 we refill with 1s.
-// NOTE 4: Special encoding for -1 offset. Extended back to 32b when decoded.
-//
-
-void retouch_encode(int32_t offset, uint32_t contents) {
- int64_t d_offs = offset-offs_prev;
- int64_t d_cont = (int64_t)contents-(int64_t)cont_prev;
-
- uint8_t output[8];
- uint32_t output_size;
-
- if ((d_offs > 3) &&
- (d_offs % 4) == 0 &&
- (d_offs / 4) < 5 &&
- (d_cont < 4000) &&
- (d_cont > -4000)) {
- // we can fit in 2 bytes
- output[0] =
- 0x80 |
- (((d_offs/4)-1) << 5) |
- (((uint64_t)d_cont & 0x1f00) >> 8);
- output[1] =
- ((uint64_t)d_cont & 0xff);
- output_size = 2;
- } else if ((d_offs > 3) &&
- (d_offs % 4) == 0 &&
- (d_offs / 4) < 5 &&
- (d_cont < 510000) &&
- (d_cont > -510000)) {
- // fit in 3 bytes
- output[0] =
- 0x40 |
- (((d_offs/4)-1) << 4) |
- (((uint64_t)d_cont & 0xf0000) >> 16);
- output[1] =
- ((uint64_t)d_cont & 0xff00) >> 8;
- output[2] =
- ((uint64_t)d_cont & 0xff);
- output_size = 3;
- } else {
- // fit in 8 bytes; we can't support files bigger than (1GB-1)
- // with this encoding: no library is that big anyway..
- FAILIF(offset < -1 || offset > 0x3ffffffe, "Offset out of range.\n");
- output[0] = (offset & 0x3f000000) >> 24;
- output[1] = (offset & 0xff0000) >> 16;
- output[2] = (offset & 0xff00) >> 8;
- output[3] = (offset & 0xff);
- output[4] = (contents & 0xff000000) >> 24;
- output[5] = (contents & 0xff0000) >> 16;
- output[6] = (contents & 0xff00) >> 8;
- output[7] = (contents & 0xff);
- output_size = 8;
- }
-
- // If this happens, the retouch buffer size can be bumped up.
- // Currently, the largest case is libwebcore, at about 250K.
- FAILIF((retouch_byte_cnt+output_size) > RETOUCH_MAX_SIZE,
- "About to overflow retouch buffer.\n");
-
- memcpy(retouch_buf+retouch_byte_cnt, output, output_size);
- retouch_byte_cnt += output_size;
-
- offs_prev = offset;
- cont_prev = contents;
-}
-
-void retouch_dump(const char *fname, int elf_little,
- unsigned int retouch_byte_cnt, char *retouch_buf) {
- int fd = open(fname, O_WRONLY);
- FAILIF(fd < 0,
- "open(%s, O_WRONLY): %s (%d)\n" ,
- fname, strerror(errno), errno);
- off_t sz = lseek(fd, 0, SEEK_END);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte
- // size of the retouch blob, in target endianness.
- strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8);
- if (elf_little ^ is_host_little()) {
- *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
- switch_endianness(retouch_byte_cnt);
- } else {
- *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
- retouch_byte_cnt;
- }
-
- int num_written = write(fd, retouch_buf, retouch_byte_cnt+12);
- FAILIF(num_written < 0,
- "write(%d, &info, sizeof(info)): %s (%d)\n",
- fd, strerror(errno), errno);
- FAILIF((retouch_byte_cnt+12) != num_written,
- "Could not write %d bytes as expected (wrote %d bytes instead)!\n",
- retouch_byte_cnt, num_written);
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
-}
-
-/* End of retouch code.
- */
-
-#if defined(DEBUG) && 0
-
-static void print_shdr(source_t *source, Elf_Scn *scn)
-{
- GElf_Shdr shdr_mem, *shdr;
- shdr = gelf_getshdr(scn, &shdr_mem);
- Elf_Data *data = elf_getdata(scn, NULL);
- INFO("\t%02d: data = %p, hdr = { offset = %8lld, size = %lld }, "
- "data->d_buf = %p data->d_off = %lld, data->d_size = %d\n",
- elf_ndxscn(scn),
- data,
- shdr->sh_offset, shdr->sh_size,
- data->d_buf, data->d_off, data->d_size);
-}
-
-static void print_shdr_idx(source_t *source, Elf *elf, int idx)
-{
- print_shdr(source, elf_getscn(elf, idx));
-}
-
-static void print_shdrs(source_t *source) {
- Elf_Scn *scn = NULL;
- INFO("section offset dump for new ELF\n");
- while ((scn = elf_nextscn (source->elf, scn)) != NULL)
- print_shdr(source, scn);
-
- INFO("\nsection offset dump for original ELF\n");
- while ((scn = elf_nextscn (source->oldelf, scn)) != NULL)
- print_shdr(source, scn);
-
-#if 0
- {
- INFO("section offset dump for new ELF\n");
- int i = 0;
- for (i = 0; i < source->shnum; i++) {
- scn = elf_getscn(source->elf, i);
- print_shdr(source, scn);
- }
- }
-#endif
-}
-
-#endif /* DEBUG */
-
-static char * find_file(const char *libname,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs);
-
-static inline source_t* find_source(const char *name,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs) {
- char *full = find_file(name, lib_lookup_dirs, num_lib_lookup_dirs);
- if (full) {
- source_t *trav = sources;
- while (trav) {
- if (!strcmp(trav->name, full))
- break;
- trav = trav->next;
- }
- free(full);
- return trav;
- }
- return NULL;
-}
-
-static inline void add_to_sources(source_t *src) {
- src->next = sources;
- sources = src;
-}
-
-static void handle_range_error(range_error_t err,
- range_t *left, range_t *right) {
- switch (err) {
- case ERROR_CONTAINS:
- ERROR("ERROR: section (%lld, %lld bytes) contains "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- case ERROR_OVERLAPS:
- ERROR("ERROR: Section (%lld, %lld bytes) intersects "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- default:
- ASSERT(!"Unknown range error code!");
- }
-
- FAILIF(1, "Range error.\n");
-}
-
-static void create_elf_sections(source_t *source, Elf *elf)
-{
- INFO("Creating new ELF sections.\n");
- ASSERT(elf == NULL || source->elf == NULL || source->elf == elf);
- if (elf == NULL) {
- ASSERT(source->elf != NULL);
- elf = source->elf;
- }
-
- int cnt = 1;
- Elf_Scn *oldscn = NULL, *scn;
- while ((oldscn = elf_nextscn (source->oldelf, oldscn)) != NULL) {
- GElf_Shdr *oldshdr, oldshdr_mem;
-
- scn = elf_newscn(elf);
- FAILIF_LIBELF(NULL == scn, elf_newscn);
-
- oldshdr = gelf_getshdr(oldscn, &oldshdr_mem);
- FAILIF_LIBELF(NULL == oldshdr, gelf_getshdr);
- /* Set the section header of the new section to be the same as the
- headset of the old section by default. */
- gelf_update_shdr(scn, oldshdr);
-
- /* Copy the section data */
- Elf_Data *olddata = elf_getdata(oldscn, NULL);
- FAILIF_LIBELF(NULL == olddata, elf_getdata);
-
- Elf_Data *data = elf_newdata(scn);
- FAILIF_LIBELF(NULL == data, elf_newdata);
- *data = *olddata;
-#if COPY_SECTION_DATA_BUFFER
- if (olddata->d_buf != NULL) {
- data->d_buf = MALLOC(data->d_size);
- memcpy(data->d_buf, olddata->d_buf, olddata->d_size);
- }
-#endif
-
- INFO("\tsection %02d: [%-30s] created\n",
- cnt,
- elf_strptr(source->oldelf,
- source->shstrndx,
- oldshdr->sh_name));
-
- if (ADJUST_ELF) {
- ASSERT(source->shdr_info != NULL);
- /* Create a new section. */
- source->shdr_info[cnt].idx = cnt;
- source->shdr_info[cnt].newscn = scn;
- source->shdr_info[cnt].data = data;
- source->shdr_info[cnt].
- use_old_shdr_for_relocation_calculations = 1;
- INFO("\tsection [%s] (old offset %lld, old size %lld) "
- "will have index %d (was %d).\n",
- source->shdr_info[cnt].name,
- source->shdr_info[cnt].old_shdr.sh_offset,
- source->shdr_info[cnt].old_shdr.sh_size,
- source->shdr_info[cnt].idx,
- elf_ndxscn(source->shdr_info[cnt].scn));
- /* Same as the next assert */
- ASSERT(elf_ndxscn (source->shdr_info[cnt].newscn) ==
- source->shdr_info[cnt].idx);
- }
-
- ASSERT(elf_ndxscn(scn) == (size_t)cnt);
- cnt++;
- }
-}
-
-/* This function sets up the shdr_info[] array of a source_t. We call it only
- when ADJUST_ELF is non-zero (i.e., support for adjusting an ELF file for
- changes in sizes and numbers of relocation sections is compiled in. Note
- that setup_shdr_info() depends only on the information in source->oldelf,
- not on source->elf.
-*/
-
-static void setup_shdr_info(source_t *source)
-{
- if (ADJUST_ELF)
- {
- /* Allocate the section-header-info buffer. */
- INFO("Allocating section-header info structure (%d) bytes...\n",
- source->shnum * sizeof (shdr_info_t));
-
- source->shdr_info = (shdr_info_t *)CALLOC(source->shnum,
- sizeof (shdr_info_t));
-
- /* Mark the SHT_NULL section as handled. */
- source->shdr_info[0].idx = 2;
-
- int cnt = 1;
- Elf_Scn *oldscn = NULL;
- while ((oldscn = elf_nextscn (source->oldelf, oldscn)) != NULL) {
- /* Copy the section header */
- ASSERT(elf_ndxscn(oldscn) == (size_t)cnt);
-
- /* Initialized the corresponding shdr_info entry */
- {
- /* Mark the section with a non-zero index. Later, when we
- decide to drop a section, we will set its idx to zero, and
- assign section numbers to the remaining sections.
- */
- source->shdr_info[cnt].idx = 1;
-
- source->shdr_info[cnt].scn = oldscn;
-
- /* NOTE: Here we pupulate the section-headset struct with the
- same values as the original section's. After the
- first run of prelink(), we will update the sh_size
- fields of those sections that need resizing.
- */
- FAILIF_LIBELF(NULL ==
- gelf_getshdr(oldscn,
- &source->shdr_info[cnt].shdr),
- gelf_getshdr);
-
- /* Get the name of the section. */
- source->shdr_info[cnt].name =
- elf_strptr (source->oldelf, source->shstrndx,
- source->shdr_info[cnt].shdr.sh_name);
-
- INFO("\tname: %s\n", source->shdr_info[cnt].name);
- FAILIF(source->shdr_info[cnt].name == NULL,
- "Malformed file: section %d name is null\n",
- cnt);
-
- /* Remember the shdr.sh_link value. We need to remember this
- value for those sections that refer to other sections. For
- example, we need to remember it for relocation-entry
- sections, because if we modify the symbol table that a
- relocation-entry section is relative to, then we need to
- patch the relocation section. By the time we get to
- deciding whether we need to patch the relocation section, we
- will have overwritten its header's sh_link field with a new
- value.
- */
- source->shdr_info[cnt].old_shdr = source->shdr_info[cnt].shdr;
- INFO("\t\toriginal sh_link: %08d\n",
- source->shdr_info[cnt].old_shdr.sh_link);
- INFO("\t\toriginal sh_addr: %lld\n",
- source->shdr_info[cnt].old_shdr.sh_addr);
- INFO("\t\toriginal sh_offset: %lld\n",
- source->shdr_info[cnt].old_shdr.sh_offset);
- INFO("\t\toriginal sh_size: %lld\n",
- source->shdr_info[cnt].old_shdr.sh_size);
-
- FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX,
- "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n");
- FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_GROUP,
- "Cannot handle sh_type SHT_GROUP!\n");
- FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
- "Cannot handle sh_type SHT_GNU_versym!\n");
- }
-
- cnt++;
- } /* for each section */
- } /* if (ADJUST_ELF) */
-}
-
-static Elf * init_elf(source_t *source, bool create_new_sections)
-{
- Elf *elf;
- if (source->output != NULL) {
- if (source->output_is_dir) {
- source->output_is_dir++;
- char *dir = source->output;
- int dirlen = strlen(dir);
- /* The main() function maintains a pointer to source->output; it
- frees the buffer after apriori() returns.
- */
- source->output = MALLOC(dirlen +
- 1 + /* slash */
- strlen(source->name) +
- 1); /* null terminator */
- strcpy(source->output, dir);
- source->output[dirlen] = '/';
- strcpy(source->output + dirlen + 1,
- basename(source->name));
- }
-
- /* Save some of the info; needed for retouching (ASLR). */
- retouch_init();
-
- source->newelf_fd = open(source->output,
- O_RDWR | O_CREAT,
- 0666);
- FAILIF(source->newelf_fd < 0, "open(%s): %s (%d)\n",
- source->output,
- strerror(errno),
- errno);
- elf = elf_begin(source->newelf_fd, ELF_C_WRITE, NULL);
- FAILIF_LIBELF(elf == NULL, elf_begin);
- } else {
- elf = elf_clone(source->oldelf, ELF_C_EMPTY);
- FAILIF_LIBELF(elf == NULL, elf_clone);
- }
-
- GElf_Ehdr *oldehdr = gelf_getehdr(source->oldelf, &source->old_ehdr_mem);
- FAILIF_LIBELF(NULL == oldehdr, gelf_getehdr);
-
- /* Create new ELF and program headers for the elf file */
- INFO("Creating empty ELF and program headers...\n");
- FAILIF_LIBELF(gelf_newehdr (elf, gelf_getclass (source->oldelf)) == 0,
- gelf_newehdr);
- FAILIF_LIBELF(oldehdr->e_type != ET_REL
- && gelf_newphdr (elf,
- oldehdr->e_phnum) == 0,
- gelf_newphdr);
-
- /* Copy the elf header */
- INFO("Copying ELF header...\n");
- GElf_Ehdr *ehdr = gelf_getehdr(elf, &source->ehdr_mem);
- FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
- memcpy(ehdr, oldehdr, sizeof(GElf_Ehdr));
- FAILIF_LIBELF(!gelf_update_ehdr(elf, ehdr), gelf_update_ehdr);
-
- /* Copy out the old program header: notice that if the ELF file does not
- have a program header, this loop won't execute.
- */
- INFO("Copying ELF program header...\n");
- {
- int cnt;
- source->phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum,
- sizeof(GElf_Phdr));
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) {
- INFO("\tRetrieving entry %d\n", cnt);
- FAILIF_LIBELF(NULL ==
- gelf_getphdr(source->oldelf, cnt,
- source->phdr_info + cnt),
- gelf_getphdr);
- FAILIF_LIBELF(gelf_update_phdr (elf, cnt,
- source->phdr_info + cnt) == 0,
- gelf_update_phdr);
- }
- }
-
- /* Copy the sections and the section headers. */
- if (create_new_sections)
- {
- create_elf_sections(source, elf);
- }
-
- /* The ELF library better follows our layout when this is not a
- relocatable object file. */
- elf_flagelf (elf, ELF_C_SET, (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0));
-
- return elf;
-}
-
-static shdr_info_t *lookup_shdr_info_by_new_section(
- source_t *source,
- const char *sname,
- Elf_Scn *newscn)
-{
- if (source->shdr_info == NULL) return NULL;
- int cnt;
- for (cnt = 0; cnt < source->shnum; cnt++) {
- if (source->shdr_info[cnt].newscn == newscn) {
- INFO("\t\tnew section at %p matches shdr_info[%d], "
- "section [%s]!\n",
- newscn,
- cnt,
- source->shdr_info[cnt].name);
- FAILIF(strcmp(sname, source->shdr_info[cnt].name),
- "Matched section's name [%s] does not match "
- "looked-up section's name [%s]!\n",
- source->shdr_info[cnt].name,
- sname);
- return source->shdr_info + cnt;
- }
- }
- return NULL;
-}
-
-static bool do_init_source(source_t *source, unsigned base)
-{
- /* Find various sections. */
- size_t scnidx;
- Elf_Scn *scn;
- GElf_Shdr *shdr, shdr_mem;
- source->sorted_sections = init_range_list();
- INFO("Processing [%s]'s sections...\n", source->name);
- for (scnidx = 1; scnidx < (size_t)source->shnum; scnidx++) {
- INFO("\tGetting section index %d...\n", scnidx);
- scn = elf_getscn(source->elf, scnidx);
- if (NULL == scn) {
- /* If we get an error from elf_getscn(), it means that a section
- at the requested index does not exist. This may happen when
- we remove sections. Since we do not update source->shnum
- (we can't, since we need to know the original number of sections
- to know source->shdr_info[]'s length), we will attempt to
- retrieve a section for an index that no longer exists in the
- new ELF file. */
- INFO("\tThere is no section at index %d anymore, continuing.\n",
- scnidx);
- continue;
- }
- shdr = gelf_getshdr(scn, &shdr_mem);
- FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
-
- /* We haven't modified the shstrtab section, and so shdr->sh_name
- has the same value as before. Thus we look up the name based
- on the old ELF handle. We cannot use shstrndx on the new ELF
- handle because the index of the shstrtab section may have
- changed (and calling elf_getshstrndx() returns the same section
- index, so libelf can't handle thise ither).
- */
- const char *sname =
- elf_strptr(source->oldelf, source->shstrndx, shdr->sh_name);
- ASSERT(sname);
-
- INFO("\tAdding [%s] (%lld, %lld)...\n",
- sname,
- shdr->sh_addr,
- shdr->sh_addr + shdr->sh_size);
- if ((shdr->sh_flags & SHF_ALLOC) == SHF_ALLOC) {
- add_unique_range_nosort(source->sorted_sections,
- shdr->sh_addr,
- shdr->sh_size,
- scn,
- handle_range_error,
- NULL); /* no user-data destructor */
- }
-
- if (shdr->sh_type == SHT_DYNSYM) {
- source->symtab.scn = scn;
- source->symtab.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->symtab.data, elf_getdata);
- memcpy(&source->symtab.shdr, shdr, sizeof(GElf_Shdr));
- source->symtab.info = lookup_shdr_info_by_new_section(
- source, sname, scn);
- ASSERT(source->shdr_info == NULL || source->symtab.info != NULL);
-
- /* The sh_link field of the section header of the symbol table
- contains the index of the associated strings table. */
- source->strtab.scn = elf_getscn(source->elf,
- source->symtab.shdr.sh_link);
- FAILIF_LIBELF(NULL == source->strtab.scn, elf_getscn);
- FAILIF_LIBELF(NULL == gelf_getshdr(source->strtab.scn,
- &source->strtab.shdr),
- gelf_getshdr);
- source->strtab.data = elf_getdata(source->strtab.scn, NULL);
- FAILIF_LIBELF(NULL == source->strtab.data, elf_getdata);
- source->strtab.info = lookup_shdr_info_by_new_section(
- source,
- elf_strptr(source->oldelf, source->shstrndx,
- source->strtab.shdr.sh_name),
- source->strtab.scn);
- ASSERT(source->shdr_info == NULL || source->strtab.info != NULL);
- } else if (shdr->sh_type == SHT_DYNAMIC) {
- source->dynamic.scn = scn;
- source->dynamic.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->dynamic.data, elf_getdata);
- memcpy(&source->dynamic.shdr, shdr, sizeof(GElf_Shdr));
- source->dynamic.info = lookup_shdr_info_by_new_section(
- source, sname, scn);
- ASSERT(source->shdr_info == NULL || source->dynamic.info != NULL);
- } else if (shdr->sh_type == SHT_HASH) {
- source->hash.scn = scn;
- source->hash.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->hash.data, elf_getdata);
- memcpy(&source->hash.shdr, shdr, sizeof(GElf_Shdr));
- source->hash.info = lookup_shdr_info_by_new_section(
- source, sname, scn);
- ASSERT(source->shdr_info == NULL || source->hash.info != NULL);
- } else if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
- if (source->num_relocation_sections ==
- source->relocation_sections_size) {
- source->relocation_sections_size += 5;
- source->relocation_sections =
- (section_info_t *)REALLOC(source->relocation_sections,
- source->relocation_sections_size *
- sizeof(section_info_t));
- }
- section_info_t *reloc =
- source->relocation_sections + source->num_relocation_sections;
- reloc->scn = scn;
- reloc->info = lookup_shdr_info_by_new_section(source, sname, scn);
- ASSERT(source->shdr_info == NULL || reloc->info != NULL);
- reloc->data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == reloc->data, elf_getdata);
- memcpy(&reloc->shdr, shdr, sizeof(GElf_Shdr));
- source->num_relocation_sections++;
- } else if (!strcmp(sname, ".bss")) {
- source->bss.scn = scn;
- source->bss.data = elf_getdata(scn, NULL);
- source->bss.info = lookup_shdr_info_by_new_section(
- source, sname, scn);
- ASSERT(source->shdr_info == NULL || source->bss.info != NULL);
- /* The BSS section occupies no space in the ELF file. */
- FAILIF_LIBELF(NULL == source->bss.data, elf_getdata)
- FAILIF(NULL != source->bss.data->d_buf,
- "Enexpected: section [%s] has data!",
- sname);
- memcpy(&source->bss.shdr, shdr, sizeof(GElf_Shdr));
- }
- }
- sort_ranges(source->sorted_sections);
-
- source->unfinished =
- (unfinished_relocation_t *)CALLOC(source->num_relocation_sections,
- sizeof(unfinished_relocation_t));
-
- if (source->dynamic.scn == NULL) {
- INFO("File [%s] does not have a dynamic section!\n", source->name);
- /* If this is a static executable, we won't update anything. */
- source->dry_run = 1;
- return false;
- }
-
- FAILIF(source->symtab.scn == NULL,
- "File [%s] does not have a dynamic symbol table!\n",
- source->name);
- FAILIF(source->hash.scn == NULL,
- "File [%s] does not have a hash table!\n",
- source->name);
- FAILIF(source->hash.shdr.sh_link != elf_ndxscn(source->symtab.scn),
- "Hash points to section %d, not to %d as expected!\n",
- source->hash.shdr.sh_link,
- elf_ndxscn(source->symtab.scn));
-
- /* Now, find out how many symbols we have and allocate the array of
- satisfied symbols.
-
- NOTE: We don't count the number of undefined symbols here; we will
- iterate over the symbol table later, and count them then, when it is
- more convenient.
- */
- size_t symsize = gelf_fsize (source->elf,
- ELF_T_SYM,
- 1, source->elf_hdr.e_version);
- ASSERT(symsize);
-
- source->num_syms = source->symtab.data->d_size / symsize;
- source->base = (source->oldelf_hdr.e_type == ET_DYN) ? base : 0;
- INFO("Relink base for [%s]: 0x%lx\n", source->name, source->base);
- FAILIF(source->base == -1,
- "Can't prelink [%s]: it's a shared library and you did not "
- "provide a prelink address!\n",
- source->name);
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- FAILIF(source->prelinked && source->base != source->prelink_base,
- "ERROR: file [%s] has already been prelinked for 0x%08lx. "
- "Cannot change to 0x%08lx!\n",
- source->name,
- source->prelink_base,
- source->base);
-#endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
-
- return true;
-}
-
-static source_t* init_source(const char *full_path,
- const char *output, int is_file,
- int base, int dry_run)
-{
- source_t *source = (source_t *)CALLOC(1, sizeof(source_t));
-
- ASSERT(full_path);
- source->name = full_path;
- source->output = output;
- source->output_is_dir = !is_file;
-
- source->newelf_fd = -1;
- source->elf_fd = -1;
- INFO("Opening %s...\n", full_path);
- source->elf_fd =
- open(full_path, ((dry_run || output != NULL) ? O_RDONLY : O_RDWR));
- FAILIF(source->elf_fd < 0, "open(%s): %s (%d)\n",
- full_path,
- strerror(errno),
- errno);
-
- FAILIF(fstat(source->elf_fd, &source->elf_file_info) < 0,
- "fstat(%s(fd %d)): %s (%d)\n",
- source->name,
- source->elf_fd,
- strerror(errno),
- errno);
- INFO("File [%s]'s size is %lld bytes!\n",
- source->name,
- source->elf_file_info.st_size);
-
- INFO("Calling elf_begin(%s)...\n", full_path);
-
- source->oldelf =
- elf_begin(source->elf_fd,
- (dry_run || output != NULL) ? ELF_C_READ : ELF_C_RDWR,
- NULL);
- FAILIF_LIBELF(source->oldelf == NULL, elf_begin);
-
- /* libelf can recognize COFF and A.OUT formats, but we handle only ELF. */
- if(elf_kind(source->oldelf) != ELF_K_ELF) {
- ERROR("Input file %s is not in ELF format!\n", full_path);
- return NULL;
- }
-
- /* Make sure this is a shared library or an executable. */
- {
- INFO("Making sure %s is a shared library or an executable...\n",
- full_path);
- FAILIF_LIBELF(0 == gelf_getehdr(source->oldelf, &source->oldelf_hdr),
- gelf_getehdr);
- FAILIF(source->oldelf_hdr.e_type != ET_DYN &&
- source->oldelf_hdr.e_type != ET_EXEC,
- "%s must be a shared library (elf type is %d, expecting %d).\n",
- full_path,
- source->oldelf_hdr.e_type,
- ET_DYN);
- }
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- /* First, check to see if the file has been prelinked. */
- source->prelinked =
- check_prelinked(source->name,
- source->oldelf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
- &source->prelink_base);
- /* Note that in the INFO() below we need to use oldelf_hdr because we
- haven't cloned the ELF file yet, and source->elf_hdr is not defined. */
- if (source->prelinked) {
- PRINT("%s [%s] is already prelinked at 0x%08lx!\n",
- (source->oldelf_hdr.e_type == ET_EXEC ?
- "Executable" : "Shared library"),
- source->name,
- source->prelink_base);
- /* Force a dry run when the file has already been prelinked */
- source->dry_run = dry_run = 1;
- }
- else {
- INFO("%s [%s] is not prelinked!\n",
- (source->oldelf_hdr.e_type == ET_EXEC ?
- "Executable" : "Shared library"),
- source->name);
- source->dry_run = dry_run;
- }
-#endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
-
- /* Get the index of the section-header-strings-table section. */
- FAILIF_LIBELF(elf_getshstrndx (source->oldelf, &source->shstrndx) < 0,
- elf_getshstrndx);
-
- FAILIF_LIBELF(elf_getshnum (source->oldelf, (size_t *)&source->shnum) < 0,
- elf_getshnum);
-
- /* When we have a dry run, or when ADJUST_ELF is enabled, we use
- source->oldelf for source->elf, because the former is mmapped privately,
- so changes to it have no effect. With ADJUST_ELF, the first run of
- prelink() is a dry run. We will reopen the elf file for write access
- after that dry run, before we call adjust_elf. */
-
- source->elf = (ADJUST_ELF || source->dry_run) ?
- source->oldelf : init_elf(source, ADJUST_ELF == 0);
-
- FAILIF_LIBELF(0 == gelf_getehdr(source->elf, &source->elf_hdr),
- gelf_getehdr);
-#ifdef DEBUG
- ASSERT(!memcmp(&source->oldelf_hdr,
- &source->elf_hdr,
- sizeof(source->elf_hdr)));
-#endif
-
- /* Get the EBL handling. The -g option is currently the only reason
- we need EBL so dont open the backend unless necessary. */
- source->ebl = ebl_openbackend (source->elf);
- FAILIF_LIBELF(NULL == source->ebl, ebl_openbackend);
-#ifdef ARM_SPECIFIC_HACKS
- FAILIF_LIBELF(0 != arm_init(source->elf, source->elf_hdr.e_machine,
- source->ebl, sizeof(Ebl)),
- arm_init);
-#endif/*ARM_SPECIFIC_HACKS*/
-
- add_to_sources(source);
- if (do_init_source(source, base) == false) return NULL;
- return source;
-}
-
-/* complements do_init_source() */
-static void do_destroy_source(source_t *source)
-{
- int cnt;
- destroy_range_list(source->sorted_sections);
- source->sorted_sections = NULL;
- for (cnt = 0; cnt < source->num_relocation_sections; cnt++) {
- FREEIF(source->unfinished[cnt].rels);
- source->unfinished[cnt].rels = NULL;
- source->unfinished[cnt].num_rels = 0;
- source->unfinished[cnt].rels_size = 0;
- }
- if (source->jmprel.sections != NULL) {
- destroy_range_list(source->jmprel.sections);
- source->jmprel.sections = NULL;
- }
- if (source->rel.sections != NULL) {
- destroy_range_list(source->rel.sections);
- source->rel.sections = NULL;
- }
- FREE(source->unfinished); /* do_init_source() */
- source->unfinished = NULL;
- FREE(source->relocation_sections); /* do_init_source() */
- source->relocation_sections = NULL;
- source->num_relocation_sections = source->relocation_sections_size = 0;
-}
-
-static void destroy_source(source_t *source)
-{
- /* Is this a little-endian ELF file? */
- if (source->oldelf != source->elf) {
- /* If it's a dynamic executable, this must not be a dry run. */
- if (!source->dry_run && source->dynamic.scn != NULL)
- {
- FAILIF_LIBELF(elf_update(source->elf, ELF_C_WRITE) == -1,
- elf_update);
- }
- FAILIF_LIBELF(elf_end(source->oldelf), elf_end);
- }
- ebl_closebackend(source->ebl);
- FAILIF_LIBELF(elf_end(source->elf), elf_end);
- FAILIF(close(source->elf_fd) < 0, "Could not close file %s: %s (%d)!\n",
- source->name, strerror(errno), errno);
- FAILIF((source->newelf_fd >= 0) && (close(source->newelf_fd) < 0),
- "Could not close output file: %s (%d)!\n", strerror(errno), errno);
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- if (!source->dry_run) {
- if (source->dynamic.scn != NULL &&
- source->elf_hdr.e_type != ET_EXEC)
- {
- /* For some reason, trying to write directly to source->elf_fd
- causes a "bad file descriptor" error because of something libelf
- does. We just close the file descriptor and open a new one in
- function setup_prelink_info() below. */
- INFO("%s: setting up prelink tag at end of file.\n",
- source->output ? source->output : source->name);
- retouch_encode(-1, source->base);
- retouch_dump(source->output ? source->output : source->name,
- source->elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
- retouch_byte_cnt,
- retouch_buf);
- setup_prelink_info(source->output ? source->output : source->name,
- source->elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
- source->base);
- }
- else INFO("%s: executable, NOT setting up prelink tag.\n",
- source->name);
- }
-#endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
-
- do_destroy_source(source);
- if (retouch_buf != NULL) { free(retouch_buf); retouch_buf = NULL; }
-
- if (source->shstrtab_data != NULL)
- FREEIF(source->shstrtab_data->d_buf); /* adjust_elf */
-
- FREE(source->lib_deps); /* list of library dependencies (process_file()) */
- FREEIF(source->shdr_info); /* setup_shdr_info() */
- FREEIF(source->phdr_info); /* init_elf() */
- FREE(source->name); /* assigned to by init_source() */
- /* If the output is a directory, in init_elf() we allocate a buffer where
- we copy the directory, a slash, and the file name. Here we free that
- buffer.
- */
- if (source->output_is_dir > 1) {
- FREE(source->output);
- }
- FREE(source); /* init_source() */
-}
-
-static void reinit_source(source_t *source)
-{
- do_destroy_source(source);
- do_init_source(source, source->base);
-
- {
- /* We've gathered all the DT_DYNAMIC entries; now we need to figure
- out which relocation sections fit in which range as described by
- the entries. Before we do so, however, we will populate the
- jmprel and rel members of source, as well as their sizes.
- */
-
- size_t dynidx, numdyn;
- GElf_Dyn *dyn, dyn_mem;
-
- numdyn = source->dynamic.shdr.sh_size /
- source->dynamic.shdr.sh_entsize;
-
- source->rel.idx = source->rel.sz_idx = -1;
- source->jmprel.idx = source->jmprel.sz_idx = -1;
- for (dynidx = 0; dynidx < numdyn; dynidx++) {
- dyn = gelf_getdyn (source->dynamic.data,
- dynidx,
- &dyn_mem);
- FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
- switch (dyn->d_tag)
- {
- case DT_NEEDED:
- break;
- case DT_JMPREL:
- INFO("reinit_source: DT_JMPREL is at index %d, 0x%08llx.\n",
- dynidx, dyn->d_un.d_ptr);
- source->jmprel.idx = dynidx;
- source->jmprel.addr = dyn->d_un.d_ptr;
- break;
- case DT_PLTRELSZ:
- INFO("reinit_source: DT_PLTRELSZ is at index %d, 0x%08llx.\n",
- dynidx, dyn->d_un.d_val);
- source->jmprel.sz_idx = dynidx;
- source->jmprel.size = dyn->d_un.d_val;
- break;
- case DT_REL:
- INFO("reinit_source: DT_REL is at index %d, 0x%08llx.\n",
- dynidx, dyn->d_un.d_ptr);
- source->rel.idx = dynidx;
- source->rel.addr = dyn->d_un.d_ptr;
- break;
- case DT_RELSZ:
- INFO("reinit_source: DT_RELSZ is at index %d, 0x%08llx.\n",
- dynidx, dyn->d_un.d_val);
- source->rel.sz_idx = dynidx;
- source->rel.size = dyn->d_un.d_val;
- break;
- case DT_RELA:
- case DT_RELASZ:
- FAILIF(1, "Can't handle DT_RELA and DT_RELASZ entries!\n");
- break;
- } /* switch */
- } /* for each dynamic entry... */
- }
-}
-
-static GElf_Sym *hash_lookup_global_or_weak_symbol(source_t *lib,
- const char *symname,
- GElf_Sym *lib_sym_mem)
-{
- int lib_symidx = hash_lookup(lib->elf,
- lib->hash.data,
- lib->symtab.data,
- lib->strtab.data,
- symname);
-
- GElf_Sym sym_mem;
- if (SHN_UNDEF != lib_symidx) {
- /* We found the symbol--now check to see if it is global
- or weak. If this is the case, then the symbol satisfies
- the dependency. */
- GElf_Sym *lib_sym = gelf_getsymshndx(lib->symtab.data,
- NULL,
- lib_symidx,
- &sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == lib_sym, gelf_getsymshndx);
-#if ELF_STRPTR_IS_BROKEN
- ASSERT(!strcmp(
- symname,
- ((char *)elf_getdata(elf_getscn(lib->elf,
- lib->symtab.shdr.sh_link),
- NULL)->d_buf) +
- lib_sym->st_name));
-#else
- ASSERT(!strcmp(
- symname,
- elf_strptr(lib->elf, lib->symtab.shdr.sh_link,
- lib_sym->st_name)));
-#endif
- if (lib_sym->st_shndx != SHN_UNDEF &&
- (GELF_ST_BIND(lib_sym->st_info) == STB_GLOBAL ||
- GELF_ST_BIND(lib_sym->st_info) == STB_WEAK)) {
- memcpy(lib_sym_mem, &sym_mem, sizeof(GElf_Sym));
- return lib_sym;
- }
- }
-
- return NULL;
-}
-
-static source_t *lookup_symbol_in_dependencies(source_t *source,
- const char *symname,
- GElf_Sym *found_sym)
-{
- source_t *sym_source = NULL; /* return value */
-
- /* This is an undefined symbol. Go over the list of libraries
- and look it up. */
- size_t libidx;
- int found = 0;
- source_t *last_found = NULL;
- for (libidx = 0; libidx < (size_t)source->num_lib_deps; libidx++) {
- source_t *lib = source->lib_deps[libidx];
- if (hash_lookup_global_or_weak_symbol(lib, symname, found_sym) != NULL)
- {
- sym_source = lib;
- if (found) {
- if (found == 1) {
- found++;
- ERROR("ERROR: multiple definitions found for [%s:%s]!\n",
- source->name, symname);
- ERROR("\tthis definition [%s]\n", lib->name);
- }
- ERROR("\tprevious definition [%s]\n", last_found->name);
- }
- last_found = lib;
- if (!found) found = 1;
- }
- }
-
-#if ELF_STRPTR_IS_BROKEN
- ASSERT(!sym_source ||
- !strcmp(symname,
- (char *)(elf_getdata(elf_getscn(
- sym_source->elf,
- sym_source->symtab.shdr.sh_link),
- NULL)->d_buf) +
- found_sym->st_name));
-#else
- ASSERT(!sym_source ||
- !strcmp(symname,
- elf_strptr(sym_source->elf,
- sym_source->symtab.shdr.sh_link,
- found_sym->st_name)));
-#endif
-
- return sym_source;
-}
-
-static int do_prelink(source_t *source,
- Elf_Data *reloc_scn_data,
- int reloc_scn_entry_size,
- unfinished_relocation_t *unfinished,
- int locals_only,
- bool dry_run,
- char **lib_lookup_dirs, int num_lib_lookup_dirs,
- char **default_libs, int num_default_libs,
- int *num_unfinished_relocs)
-{
- int num_relocations = 0;
-
- size_t num_rels;
- num_rels = reloc_scn_data->d_size / reloc_scn_entry_size;
-
- INFO("\tThere are %d relocations.\n", num_rels);
-
- int rel_idx;
- for (rel_idx = 0; rel_idx < (size_t)num_rels; rel_idx++) {
- GElf_Rel *rel, rel_mem;
-
- //INFO("\tHandling relocation %d/%d\n", rel_idx, num_rels);
-
- rel = gelf_getrel(reloc_scn_data, rel_idx, &rel_mem);
- FAILIF_LIBELF(rel == NULL, gelf_getrel);
- GElf_Sym *sym = NULL, sym_mem;
- unsigned sym_idx = GELF_R_SYM(rel->r_info);
- source_t *sym_source = NULL;
- /* found_sym points to found_sym_mem, when sym_source != NULL, and
- to sym, when the sybmol is locally defined. If the symbol is
- not locally defined and sym_source == NULL, then sym is not
- defined either. */
- GElf_Sym *found_sym = NULL, found_sym_mem;
- const char *symname = NULL;
- int sym_is_local = 1;
- if (sym_idx) {
- sym = gelf_getsymshndx(source->symtab.data,
- NULL,
- sym_idx,
- &sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
-#if ELF_STRPTR_IS_BROKEN
- symname =
- ((char *)source->strtab.data->d_buf) +
- sym->st_name;
-#else
- symname = elf_strptr(source->elf,
- elf_ndxscn(source->strtab.scn),
- sym->st_name);
-#endif
-
- /* If the symbol is defined and is either not in the BSS
- section, or if it is in the BSS then the relocation is
- not a copy relocation, then the symbol's source is this
- library (i.e., it is locally-defined). Otherwise, the
- symbol is imported.
- */
-
- sym_is_local = 0;
- if (sym->st_shndx != SHN_UNDEF &&
- (source->bss.scn == NULL ||
- sym->st_shndx != elf_ndxscn(source->bss.scn) ||
-#ifdef ARM_SPECIFIC_HACKS
- GELF_R_TYPE(rel->r_info) != R_ARM_COPY
-#else
- 1
-#endif
- ))
- {
- sym_is_local = 1;
- }
-
- if (sym_is_local) {
- INFO("\t\tSymbol [%s:%s] is defined locally.\n",
- source->name,
- symname);
- sym_source = source;
- found_sym = sym;
- }
- else if (!locals_only) {
- sym_source = lookup_symbol_in_dependencies(source,
- symname,
- &found_sym_mem);
-
- /* The symbol was not in the list of dependencies, which by
- itself is an error: it means either that the symbol does
- not exist anywhere, or that the library which has the symbol
- has not been listed as a dependency in this library or
- executable. It could also mean (for a library) that the
- symbol is defined in the executable that links agsinst it,
- which is obviously not a good thing. These are bad things,
- but they do happen, which is why we have the ability to
- provide a list of default dependencies, including
- executables. Here we check to see if the symbol has been
- defined in any of them.
- */
- if (NULL == sym_source) {
- INFO("\t\tChecking default dependencies...\n");
- int i;
- source_t *lib, *old_sym_source = NULL;
- int printed_initial_error = 0;
- for (i = 0; i < num_default_libs; i++) {
- INFO("\tChecking in [%s].\n", default_libs[i]);
- lib = find_source(default_libs[i],
- lib_lookup_dirs,
- num_lib_lookup_dirs);
- FAILIF(NULL == lib,
- "Can't find default library [%s]!\n",
- default_libs[i]);
- if (hash_lookup_global_or_weak_symbol(lib,
- symname,
- &found_sym_mem)) {
- found_sym = &found_sym_mem;
- sym_source = lib;
-#if ELF_STRPTR_IS_BROKEN
- ASSERT(!strcmp(symname,
- (char *)(elf_getdata(
- elf_getscn(
- sym_source->elf,
- sym_source->symtab.
- shdr.sh_link),
- NULL)->d_buf) +
- found_sym->st_name));
-#else
- ASSERT(!strcmp(symname,
- elf_strptr(sym_source->elf,
- sym_source->symtab.shdr.sh_link,
- found_sym->st_name)));
-
-#endif
- INFO("\tFound symbol [%s] in [%s]!\n",
- symname, lib->name);
- if (old_sym_source) {
- if (printed_initial_error == 0) {
- printed_initial_error = 1;
- ERROR("Multiple definition of [%s]:\n"
- "\t[%s]\n",
- symname,
- old_sym_source->name);
- }
- ERROR("\t[%s]\n", sym_source->name);
- }
- old_sym_source = sym_source;
- } else {
- INFO("\tCould not find symbol [%s] in default "
- "lib [%s]!\n", symname, lib->name);
- }
- }
- if (sym_source) {
- ERROR("ERROR: Could not find [%s:%s] in dependent "
- "libraries (but found in default [%s])!\n",
- source->name,
- symname,
- sym_source->name);
- }
- } else {
- found_sym = &found_sym_mem;
- /* We found the symbol in a dependency library. */
- INFO("\t\tSymbol [%s:%s, value %lld] is imported from [%s]\n",
- source->name,
- symname,
- found_sym->st_value,
- sym_source->name);
- }
- } /* if symbol is defined in this library... */
-
- if (!locals_only) {
- /* If a symbol is weak and we haven't found it, then report
- an error. We really need to find a way to set its value
- to zero. The problem is that it needs to refer to some
- section. */
-
- FAILIF(NULL == sym_source &&
- GELF_ST_BIND(sym->st_info) == STB_WEAK,
- "Cannot handle weak symbols yet (%s:%s <- %s).\n",
- source->name,
- symname,
- sym_source->name);
-#ifdef PERMISSIVE
- if (GELF_ST_BIND(sym->st_info) != STB_WEAK &&
- NULL == sym_source) {
- ERROR("ERROR: Can't find symbol [%s:%s] in dependent or "
- "default libraries!\n", source->name, symname);
- }
-#else
- FAILIF(GELF_ST_BIND(sym->st_info) != STB_WEAK &&
- NULL == sym_source,
- "Can't find symbol [%s:%s] in dependent or default "
- "libraries!\n",
- source->name,
- symname);
-#endif
- } /* if (!locals_only) */
- }
-#if 0 // too chatty
- else
- INFO("\t\tno symbol is associated with this relocation\n");
-#endif
-
-
- // We prelink only local symbols when locals_only == 1.
-
- bool can_relocate = true;
- if (!sym_is_local &&
- (symname[0] == 'd' && symname[1] == 'l' && symname[2] != '\0' &&
- (!strcmp(symname + 2, "open") ||
- !strcmp(symname + 2, "close") ||
- !strcmp(symname + 2, "sym") ||
- !strcmp(symname + 2, "error")))) {
- INFO("********* NOT RELOCATING LIBDL SYMBOL [%s]\n", symname);
- can_relocate = false;
- }
-
- if (can_relocate && (sym_is_local || !locals_only))
- {
- GElf_Shdr shdr_mem; Elf_Scn *scn; Elf_Data *data;
- find_section(source, rel->r_offset, &scn, &shdr_mem, &data);
- unsigned *dest =
- (unsigned*)(((char *)data->d_buf) +
- (rel->r_offset - shdr_mem.sh_addr));
- unsigned rel_type = GELF_R_TYPE(rel->r_info);
- char buf[64];
- INFO("\t\t%-15s ",
- ebl_reloc_type_name(source->ebl,
- GELF_R_TYPE(rel->r_info),
- buf,
- sizeof(buf)));
-
- /* Section-name offsets do not change, so we use oldelf to get the
- strings. This makes a difference in the second pass of the
- perlinker, after the call to adjust_elf, because
- source->shstrndx no longer contains the index of the
- section-header-strings table.
- */
- const char *sname = elf_strptr(
- source->oldelf, source->shstrndx, shdr_mem.sh_name);
-
- switch (rel_type) {
- case R_ARM_JUMP_SLOT:
- case R_ARM_GLOB_DAT:
- case R_ARM_ABS32:
- ASSERT(data->d_buf != NULL);
- ASSERT(data->d_size >= rel->r_offset - shdr_mem.sh_addr);
-#ifdef PERMISSIVE
- if (sym_source == NULL) {
- ERROR("ERROR: Permissive relocation "
- "[%-15s] [%s:%s]: [0x%llx] = ZERO\n",
- ebl_reloc_type_name(source->ebl,
- GELF_R_TYPE(rel->r_info),
- buf,
- sizeof(buf)),
- sname,
- symname,
- rel->r_offset);
- if (!dry_run)
- *dest = 0;
- } else
-#endif
- {
- ASSERT(sym_source);
- INFO("[%s:%s]: [0x%llx] = 0x%llx + 0x%lx\n",
- sname,
- symname,
- rel->r_offset,
- found_sym->st_value,
- sym_source->base);
- if (!dry_run) {
- PRINT("WARNING: Relocation type not supported "
- "for retouching!");
- *dest = found_sym->st_value + sym_source->base;
- }
- }
- num_relocations++;
- break;
- case R_ARM_RELATIVE:
- ASSERT(data->d_buf != NULL);
- ASSERT(data->d_size >= rel->r_offset - shdr_mem.sh_addr);
- FAILIF(sym != NULL,
- "Unsupported RELATIVE form (symbol != 0)...\n");
- INFO("[%s:%s]: [0x%llx] = 0x%x + 0x%lx\n",
- sname,
- symname ?: "(symbol has no name)",
- rel->r_offset, *dest, source->base);
- if (!dry_run) {
- *dest += source->base;
-
- /* Output an entry for the ASLR touch-up process. */
- retouch_encode(rel->r_offset
- -shdr_mem.sh_addr
- +shdr_mem.sh_offset,
- *dest);
- }
- num_relocations++;
- break;
- case R_ARM_COPY:
-#ifdef PERMISSIVE
- if (sym_source == NULL) {
- ERROR("ERROR: Permissive relocation "
- "[%-15s] [%s:%s]: NOT PERFORMING\n",
- ebl_reloc_type_name(source->ebl,
- GELF_R_TYPE(rel->r_info),
- buf,
- sizeof(buf)),
- sname,
- symname);
- } else
-#endif
- {
- ASSERT(sym);
- ASSERT(sym_source);
- GElf_Shdr src_shdr_mem;
- Elf_Scn *src_scn;
- Elf_Data *src_data;
- find_section(sym_source, found_sym->st_value,
- &src_scn,
- &src_shdr_mem,
- &src_data);
- INFO("Found [%s:%s (%lld)] in section [%s] .\n",
- sym_source->name,
- symname,
- found_sym->st_value,
-#if ELF_STRPTR_IS_BROKEN
- (((char *)elf_getdata(
- elf_getscn(sym_source->elf,
- sym_source->shstrndx),
- NULL)->d_buf) + src_shdr_mem.sh_name)
-#else
- elf_strptr(sym_source->elf,
- sym_source->shstrndx,
- src_shdr_mem.sh_name)
-#endif
- );
-
- unsigned *src = NULL;
- if (src_data->d_buf == NULL)
- {
-#ifdef PERMISSIVE
- if (sym_source->bss.scn == NULL ||
- elf_ndxscn(src_scn) !=
- elf_ndxscn(sym_source->bss.scn)) {
- ERROR("ERROR: Permissive relocation (NULL source "
- "not from .bss) [%-15s] [%s:%s]: "
- "NOT PERFORMING\n",
- ebl_reloc_type_name(source->ebl,
- GELF_R_TYPE(rel->r_info),
- buf,
- sizeof(buf)),
- sname,
- symname);
- }
-#endif
- }
- else {
- ASSERT(src_data->d_size >=
- found_sym->st_value - src_shdr_mem.sh_addr);
- src = (unsigned*)(((char *)src_data->d_buf) +
- (found_sym->st_value -
- src_shdr_mem.sh_addr));
- }
- ASSERT(symname);
- INFO("[%s:%s]: [0x%llx] <- [0x%llx] size %lld\n",
- sname,
- symname, rel->r_offset,
- found_sym->st_value,
- found_sym->st_size);
-
-#ifdef PERMISSIVE
- if (src_data->d_buf != NULL ||
- (sym_source->bss.scn != NULL &&
- elf_ndxscn(src_scn) ==
- elf_ndxscn(sym_source->bss.scn)))
-#endif/*PERMISSIVE*/
- {
- if (data->d_buf == NULL) {
- INFO("Incomplete relocation [%-15s] of [%s:%s].\n",
- ebl_reloc_type_name(source->ebl,
- GELF_R_TYPE(rel->r_info),
- buf,
- sizeof(buf)),
- sname,
- symname);
- FAILIF(unfinished == NULL,
- "You passed unfinished as NULL expecting "
- "to handle all relocations, "
- "but at least one cannot be handled!\n");
- if (unfinished->num_rels == unfinished->rels_size) {
- unfinished->rels_size += 10;
- unfinished->rels = (GElf_Rel *)REALLOC(
- unfinished->rels,
- unfinished->rels_size *
- sizeof(GElf_Rel));
- }
- unfinished->rels[unfinished->num_rels++] = *rel;
- num_relocations--;
- (*num_unfinished_relocs)++;
- }
- else {
- if (src_data->d_buf != NULL)
- {
- ASSERT(data->d_buf != NULL);
- ASSERT(data->d_size >= rel->r_offset -
- shdr_mem.sh_addr);
- if (!dry_run) {
- PRINT("WARNING: Relocation type not supported "
- "for retouching!");
- memcpy(dest, src, found_sym->st_size);
- }
- }
- else {
- ASSERT(src == NULL);
- ASSERT(elf_ndxscn(src_scn) ==
- elf_ndxscn(sym_source->bss.scn));
- if (!dry_run) {
- PRINT("WARNING: Relocation type not supported "
- "for retouching!");
- memset(dest, 0, found_sym->st_size);
- }
- }
- }
- }
- num_relocations++;
- }
- break;
- default:
- FAILIF(1, "Unknown relocation type %d!\n", rel_type);
- } // switch
- } // relocate
- else {
- INFO("\t\tNot relocating symbol [%s]%s\n",
- symname,
- (can_relocate ? ", relocating only locals" :
- ", which is a libdl symbol"));
- FAILIF(unfinished == NULL,
- "You passed unfinished as NULL expecting to handle all "
- "relocations, but at least one cannot be handled!\n");
- if (unfinished->num_rels == unfinished->rels_size) {
- unfinished->rels_size += 10;
- unfinished->rels = (GElf_Rel *)REALLOC(
- unfinished->rels,
- unfinished->rels_size *
- sizeof(GElf_Rel));
- }
- unfinished->rels[unfinished->num_rels++] = *rel;
- (*num_unfinished_relocs)++;
- }
- } // for each relocation entry
-
- return num_relocations;
-}
-
-static int prelink(source_t *source,
- int locals_only,
- bool dry_run,
- char **lib_lookup_dirs, int num_lib_lookup_dirs,
- char **default_libs, int num_default_libs,
- int *num_unfinished_relocs)
-{
- INFO("Prelinking [%s] (number of relocation sections: %d)%s...\n",
- source->name, source->num_relocation_sections,
- (dry_run ? " (dry run)" : ""));
- int num_relocations = 0;
- int rel_scn_idx;
- for (rel_scn_idx = 0; rel_scn_idx < source->num_relocation_sections;
- rel_scn_idx++)
- {
- section_info_t *reloc_scn = source->relocation_sections + rel_scn_idx;
- unfinished_relocation_t *unfinished = source->unfinished + rel_scn_idx;
-
- /* We haven't modified the shstrtab section, and so shdr->sh_name has
- the same value as before. Thus we look up the name based on the old
- ELF handle. We cannot use shstrndx on the new ELF handle because
- the index of the shstrtab section may have changed (and calling
- elf_getshstrndx() returns the same section index, so libelf can't
- handle thise ither).
-
- If reloc_scn->info is available, we can assert that the
- section-name has not changed. If this assertion fails,
- then we cannot use the elf_strptr() trick below to get
- the section name. One solution would be to save it in
- the section_info_t structure.
- */
- ASSERT(reloc_scn->info == NULL ||
- reloc_scn->shdr.sh_name == reloc_scn->info->old_shdr.sh_name);
- const char *sname =
- elf_strptr(source->oldelf,
- source->shstrndx,
- reloc_scn->shdr.sh_name);
- ASSERT(sname != NULL);
-
- INFO("\n\tIterating relocation section [%s]...\n", sname);
-
- /* In general, the new size of the section differs from the original
- size of the section, because we can handle some of the relocations.
- This was communicated to adjust_elf, which modified the ELF file
- according to the new section sizes. Now, when prelink() does the
- actual work of prelinking, it needs to know the original size of the
- relocation section so that it can see all of the original relocation
- entries!
- */
- size_t d_size = reloc_scn->data->d_size;
- if (reloc_scn->info != NULL &&
- reloc_scn->data->d_size != reloc_scn->info->old_shdr.sh_size)
- {
- INFO("Setting size of section [%s] to from new size %d to old "
- "size %lld temporarily (so prelinker can see all "
- "relocations).\n",
- reloc_scn->info->name,
- d_size,
- reloc_scn->info->old_shdr.sh_size);
- reloc_scn->data->d_size = reloc_scn->info->old_shdr.sh_size;
- }
-
- num_relocations +=
- do_prelink(source,
- reloc_scn->data, reloc_scn->shdr.sh_entsize,
- unfinished,
- locals_only, dry_run,
- lib_lookup_dirs, num_lib_lookup_dirs,
- default_libs, num_default_libs,
- num_unfinished_relocs);
-
- if (reloc_scn->data->d_size != d_size)
- {
- ASSERT(reloc_scn->info != NULL);
- INFO("Resetting size of section [%s] to %d\n",
- reloc_scn->info->name,
- d_size);
- reloc_scn->data->d_size = d_size;
- }
- }
-
- /* Now prelink those relocation sections which were fully handled, and
- therefore removed. They are not a part of the
- source->relocation_sections[] array anymore, but we can find them by
- scanning source->shdr_info[] and looking for sections with idx == 0.
- */
-
- if (ADJUST_ELF && source->shdr_info != NULL) {
- /* Walk over the shdr_info[] array to see if we've removed any
- relocation sections. prelink() those sections as well.
- */
- int i;
- for (i = 0; i < source->shnum; i++) {
- shdr_info_t *info = source->shdr_info + i;
- if (info->idx == 0 &&
- (info->shdr.sh_type == SHT_REL ||
- info->shdr.sh_type == SHT_RELA)) {
-
- Elf_Data *data = elf_getdata(info->scn, NULL);
- ASSERT(data->d_size == 0);
- data->d_size = info->old_shdr.sh_size;
-
- INFO("\n\tIterating relocation section [%s], which was "
- "discarded (size %d, entry size %lld).\n",
- info->name,
- data->d_size,
- info->old_shdr.sh_entsize);
-
- num_relocations +=
- do_prelink(source,
- data, info->old_shdr.sh_entsize,
- NULL, /* the section was fully handled */
- locals_only, dry_run,
- lib_lookup_dirs, num_lib_lookup_dirs,
- default_libs, num_default_libs,
- num_unfinished_relocs);
-
- data->d_size = 0;
- }
- }
- }
- return num_relocations;
-}
-
-static char * find_file(const char *libname,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs) {
- if (libname[0] == '/') {
- /* This is an absolute path name--just return it. */
- /* INFO("ABSOLUTE PATH: [%s].\n", libname); */
- return strdup(libname);
- } else {
- /* First try the working directory. */
- int fd;
- if ((fd = open(libname, O_RDONLY)) > 0) {
- close(fd);
- /* INFO("FOUND IN CURRENT DIR: [%s].\n", libname); */
- return strdup(libname);
- } else {
- /* Iterate over all library paths. For each path, append the file
- name and see if there is a file at that place. If that fails,
- bail out. */
-
- char *name;
- while (num_lib_lookup_dirs--) {
- size_t lib_len = strlen(*lib_lookup_dirs);
- /* one extra character for the slash, and another for the
- terminating NULL. */
- name = (char *)MALLOC(lib_len + strlen(libname) + 2);
- strcpy(name, *lib_lookup_dirs);
- name[lib_len] = '/';
- strcpy(name + lib_len + 1, libname);
- if ((fd = open(name, O_RDONLY)) > 0) {
- close(fd);
- /* INFO("FOUND: [%s] in [%s].\n", libname, name); */
- return name;
- }
- INFO("NOT FOUND: [%s] in [%s].\n", libname, name);
- free(name);
- }
- }
- }
- return NULL;
-}
-
-static void adjust_dynamic_segment_entry_size(source_t *source,
- dt_rel_info_t *dyn)
-{
- /* Update the size entry in the DT_DYNAMIC segment. */
- GElf_Dyn *dyn_entry, dyn_entry_mem;
- dyn_entry = gelf_getdyn(source->dynamic.data,
- dyn->sz_idx,
- &dyn_entry_mem);
- FAILIF_LIBELF(NULL == dyn_entry, gelf_getdyn);
- /* If we are calling this function to adjust the size of the dynamic entry,
- then there should be some unfinished relocations remaining. If there
- are none, then we should remove the entry from the dynamic section
- altogether.
- */
- ASSERT(dyn->num_unfinished_relocs);
-
- size_t relsize = gelf_fsize(source->elf,
- ELF_T_REL,
- 1,
- source->elf_hdr.e_version);
-
- if (unlikely(verbose_flag)) {
- char buf[64];
- INFO("Updating entry %d: [%-10s], %08llx --> %08x\n",
- dyn->sz_idx,
- ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
- buf, sizeof (buf)),
- dyn_entry->d_un.d_val,
- dyn->num_unfinished_relocs * relsize);
- }
-
- dyn_entry->d_un.d_val = dyn->num_unfinished_relocs * relsize;
-
- FAILIF_LIBELF(!gelf_update_dyn(source->dynamic.data,
- dyn->sz_idx,
- dyn_entry),
- gelf_update_dyn);
-}
-
-static void adjust_dynamic_segment_entries(source_t *source)
-{
- /* This function many remove entries from the dynamic segment, but it won't
- resize the relevant section. It'll just fill the remainted with empty
- DT entries.
-
- FIXME: This is not guaranteed right now. If a dynamic segment does not
- end with null DT entries, I think this will break.
- */
- FAILIF(source->rel.processed,
- "More than one section matches DT_REL entry in dynamic segment!\n");
- FAILIF(source->jmprel.processed,
- "More than one section matches DT_JMPREL entry in "
- "dynamic segment!\n");
- source->rel.processed =
- source->jmprel.processed = 1;
-
- if (source->rel.num_unfinished_relocs > 0)
- adjust_dynamic_segment_entry_size(source, &source->rel);
-
- if (source->jmprel.num_unfinished_relocs > 0)
- adjust_dynamic_segment_entry_size(source, &source->jmprel);
-
- /* If at least one of the entries is empty, then we need to remove it. We
- have already adjusted the size of the other.
- */
- if (source->rel.num_unfinished_relocs == 0 ||
- source->jmprel.num_unfinished_relocs == 0)
- {
- /* We need to delete the DT_REL/DT_RELSZ and DT_PLTREL/DT_PLTRELSZ
- entries from the dynamic segment. */
-
- GElf_Dyn *dyn_entry, dyn_entry_mem;
- size_t dynidx, updateidx;
-
- size_t numdyn =
- source->dynamic.shdr.sh_size /
- source->dynamic.shdr.sh_entsize;
-
- for (updateidx = dynidx = 0; dynidx < numdyn; dynidx++)
- {
- dyn_entry = gelf_getdyn(source->dynamic.data,
- dynidx,
- &dyn_entry_mem);
- FAILIF_LIBELF(NULL == dyn_entry, gelf_getdyn);
- if ((source->rel.num_unfinished_relocs == 0 &&
- (dynidx == source->rel.idx ||
- dynidx == source->rel.sz_idx)) ||
- (source->jmprel.num_unfinished_relocs == 0 &&
- (dynidx == source->jmprel.idx ||
- dynidx == source->jmprel.sz_idx)))
- {
- if (unlikely(verbose_flag)) {
- char buf[64];
- INFO("\t(!)\tRemoving entry %02d: [%-10s], %08llx\n",
- dynidx,
- ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
- buf, sizeof (buf)),
- dyn_entry->d_un.d_val);
- }
- continue;
- }
-
- if (unlikely(verbose_flag)) {
- char buf[64];
- INFO("\t\tKeeping entry %02d: [%-10s], %08llx\n",
- dynidx,
- ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
- buf, sizeof (buf)),
- dyn_entry->d_un.d_val);
- }
-
- gelf_update_dyn(source->dynamic.data,
- updateidx,
- &dyn_entry_mem);
- updateidx++;
- }
- }
-} /* adjust_dynamic_segment_entries */
-
-static bool adjust_dynamic_segment_for(source_t *source,
- dt_rel_info_t *dyn,
- bool adjust_section_size_only)
-{
- bool dropped_sections = false;
-
- /* Go over the sections that belong to this dynamic range. */
- dyn->num_unfinished_relocs = 0;
- if (dyn->sections) {
- int num_scns, idx;
- range_t *scns = get_sorted_ranges(dyn->sections, &num_scns);
-
- INFO("\tdynamic range %s:[%lld, %lld) contains %d sections.\n",
- source->name,
- dyn->addr,
- dyn->addr + dyn->size,
- num_scns);
-
- ASSERT(scns);
- int next_idx = 0, next_rel_off = 0;
- /* The total number of unfinished relocations for this dynamic
- * entry. */
- section_info_t *next = (section_info_t *)scns[next_idx].user;
- section_info_t *first = next;
- ASSERT(first);
- for (idx = 0; idx < num_scns; idx++) {
- section_info_t *reloc_scn = (section_info_t *)scns[idx].user;
- size_t rel_scn_idx = reloc_scn - source->relocation_sections;
- ASSERT(rel_scn_idx < (size_t)source->num_relocation_sections);
- unfinished_relocation_t *unfinished =
- &source->unfinished[rel_scn_idx];
- int unf_idx;
-
- ASSERT(reloc_scn->info == NULL ||
- reloc_scn->shdr.sh_name ==
- reloc_scn->info->old_shdr.sh_name);
- const char *sname =
- elf_strptr(source->oldelf,
- source->shstrndx,
- reloc_scn->shdr.sh_name);
-
- INFO("\tsection [%s] contains %d unfinished relocs.\n",
- sname,
- unfinished->num_rels);
-
- for (unf_idx = 0; unf_idx < unfinished->num_rels; unf_idx++)
- {
- /* There are unfinished relocations. Copy them forward to the
- lowest section we can. */
-
- while (next_rel_off ==
- (int)(next->shdr.sh_size/next->shdr.sh_entsize))
- {
- INFO("\tsection [%s] has filled up with %d unfinished "
- "relocs.\n",
- sname,
- next_rel_off);
-
- next_idx++;
- ASSERT(next_idx <= idx);
- next = (section_info_t *)scns[next_idx].user;
- next_rel_off = 0;
- }
-
- if (!adjust_section_size_only) {
- INFO("\t\tmoving unfinished relocation %2d to [%s:%d]\n",
- unf_idx,
- sname,
- next_rel_off);
- FAILIF_LIBELF(0 ==
- gelf_update_rel(next->data,
- next_rel_off,
- &unfinished->rels[unf_idx]),
- gelf_update_rel);
- }
-
- next_rel_off++;
- dyn->num_unfinished_relocs++;
- }
- } /* for */
-
- /* Set the size of the last section, and mark all subsequent
- sections for removal. At this point, next is the section
- to which we last wrote data, next_rel_off is the offset before
- which we wrote the last relocation, and so next_rel_off *
- relsize is the new size of the section.
- */
-
- bool adjust_file = ADJUST_ELF && source->elf_hdr.e_type != ET_EXEC;
- if (adjust_file && !source->dry_run)
- {
- size_t relsize = gelf_fsize(source->elf,
- ELF_T_REL,
- 1,
- source->elf_hdr.e_version);
-
- ASSERT(next->info == NULL ||
- next->shdr.sh_name == next->info->old_shdr.sh_name);
- const char *sname =
- elf_strptr(source->oldelf,
- source->shstrndx,
- next->shdr.sh_name);
-
- INFO("\tsection [%s] (index %d) has %d unfinished relocs, "
- "changing its size to %ld bytes (from %ld bytes).\n",
- sname,
- elf_ndxscn(next->scn),
- next_rel_off,
- (long)(next_rel_off * relsize),
- (long)(next->shdr.sh_size));
-
- /* source->shdr_info[] must be allocated prior to calling this
- function. This is in fact done in process_file(), by calling
- setup_shdr_info() just before we call adjust_dynamic_segment().
- */
- ASSERT(source->shdr_info != NULL);
-
- /* We do not update the data field of shdr_info[], because it does
- not exist yet (with ADJUST_ELF != 0). We create the new section
- and section data after the first call to prelink(). For now, we
- save the results of our analysis by modifying the sh_size field
- of the section header. When we create the new sections' data,
- we set the size of the data from the sh_size fields of the
- section headers.
-
- NOTE: The assertion applies only to the first call of
- adjust_dynamic_segment (which calls this function). By
- the second call, we've already created the data for the
- new sections. The only sections for which we haven't
- created data are the relocation sections we are removing.
- */
-#ifdef DEBUG
- ASSERT((!adjust_section_size_only &&
- (source->shdr_info[elf_ndxscn(next->scn)].idx > 0)) ||
- source->shdr_info[elf_ndxscn(next->scn)].data == NULL);
-#endif
-
- //FIXME: what else do we need to do here? Do we need to update
- // another copy of the shdr so that it's picked up when we
- // commit the file?
- next->shdr.sh_size = next_rel_off * relsize;
- source->shdr_info[elf_ndxscn(next->scn)].shdr.sh_size =
- next->shdr.sh_size;
- if (next_rel_off * relsize == 0) {
-#ifdef REMOVE_HANDLED_SECTIONS
- INFO("\tsection [%s] (index %d) is now empty, marking for "
- "removal.\n",
- sname,
- elf_ndxscn(next->scn));
- source->shdr_info[elf_ndxscn(next->scn)].idx = 0;
- dropped_sections = true;
-#endif
- }
-
- while (++next_idx < num_scns) {
- next = (section_info_t *)scns[next_idx].user;
-#ifdef REMOVE_HANDLED_SECTIONS
- ASSERT(next->info == NULL ||
- next->shdr.sh_name == next->info->old_shdr.sh_name);
- const char *sname =
- elf_strptr(source->oldelf,
- source->shstrndx,
- next->shdr.sh_name);
- INFO("\tsection [%s] (index %d) is now empty, marking for "
- "removal.\n",
- sname,
- elf_ndxscn(next->scn));
- /* mark for removal */
- source->shdr_info[elf_ndxscn(next->scn)].idx = 0;
- dropped_sections = true;
-#endif
- }
- }
-
- } /* if (dyn->sections) */
- else {
- /* The dynamic entry won't have any sections when it itself doesn't
- exist. This could happen when we remove all relocation sections
- from a dynamic entry because we have managed to handle all
- relocations in them.
- */
- INFO("\tNo section for dynamic entry!\n");
- }
-
- return dropped_sections;
-}
-
-static bool adjust_dynamic_segment(source_t *source,
- bool adjust_section_size_only)
-{
- bool dropped_section;
- INFO("Adjusting dynamic segment%s.\n",
- (adjust_section_size_only ? " (section sizes only)" : ""));
- INFO("\tadjusting dynamic segment REL.\n");
- dropped_section =
- adjust_dynamic_segment_for(source, &source->rel,
- adjust_section_size_only);
- INFO("\tadjusting dynamic segment JMPREL.\n");
- dropped_section =
- adjust_dynamic_segment_for(source, &source->jmprel,
- adjust_section_size_only) ||
- dropped_section;
- if (!adjust_section_size_only)
- adjust_dynamic_segment_entries(source);
- return dropped_section;
-}
-
-static void match_relocation_sections_to_dynamic_ranges(source_t *source)
-{
- /* We've gathered all the DT_DYNAMIC entries; now we need to figure out
- which relocation sections fit in which range as described by the
- entries.
- */
-
- int relidx;
- for (relidx = 0; relidx < source->num_relocation_sections; relidx++) {
- section_info_t *reloc_scn = &source->relocation_sections[relidx];
-
- int index = elf_ndxscn(reloc_scn->scn);
-
- ASSERT(reloc_scn->info == NULL ||
- reloc_scn->shdr.sh_name == reloc_scn->info->old_shdr.sh_name);
- const char *sname =
- elf_strptr(source->oldelf,
- source->shstrndx,
- reloc_scn->shdr.sh_name);
-
- INFO("Checking section [%s], index %d, for match to dynamic ranges\n",
- sname, index);
- if (source->shdr_info == NULL || reloc_scn->info->idx > 0) {
- if (source->rel.addr &&
- source->rel.addr <= reloc_scn->shdr.sh_addr &&
- reloc_scn->shdr.sh_addr < source->rel.addr + source->rel.size)
- {
- /* The entire section must fit in the dynamic range. */
- if((reloc_scn->shdr.sh_addr + reloc_scn->shdr.sh_size) >
- (source->rel.addr + source->rel.size))
- {
- PRINT("WARNING: In [%s], section %s:[%lld,%lld) "
- "is not fully contained in dynamic range "
- "[%lld,%lld)!\n",
- source->name,
- sname,
- reloc_scn->shdr.sh_addr,
- reloc_scn->shdr.sh_addr +
- reloc_scn->shdr.sh_size,
- source->rel.addr,
- source->rel.addr + source->rel.size);
- }
-
- if (NULL == source->rel.sections) {
- source->rel.sections = init_range_list();
- ASSERT(source->rel.sections);
- }
- add_unique_range_nosort(source->rel.sections,
- reloc_scn->shdr.sh_addr,
- reloc_scn->shdr.sh_size,
- reloc_scn,
- NULL,
- NULL);
- INFO("\tSection [%s] matches dynamic range REL.\n",
- sname);
- }
- else if (source->jmprel.addr &&
- source->jmprel.addr <= reloc_scn->shdr.sh_addr &&
- reloc_scn->shdr.sh_addr <= source->jmprel.addr +
- source->jmprel.size)
- {
- if((reloc_scn->shdr.sh_addr + reloc_scn->shdr.sh_size) >
- (source->jmprel.addr + source->jmprel.size))
- {
- PRINT("WARNING: In [%s], section %s:[%lld,%lld) "
- "is not fully "
- "contained in dynamic range [%lld,%lld)!\n",
- source->name,
- sname,
- reloc_scn->shdr.sh_addr,
- reloc_scn->shdr.sh_addr +
- reloc_scn->shdr.sh_size,
- source->jmprel.addr,
- source->jmprel.addr + source->jmprel.size);
- }
-
- if (NULL == source->jmprel.sections) {
- source->jmprel.sections = init_range_list();
- ASSERT(source->jmprel.sections);
- }
- add_unique_range_nosort(source->jmprel.sections,
- reloc_scn->shdr.sh_addr,
- reloc_scn->shdr.sh_size,
- reloc_scn,
- NULL,
- NULL);
- INFO("\tSection [%s] matches dynamic range JMPREL.\n",
- sname);
- }
- else
- PRINT("WARNING: Relocation section [%s:%s] does not match "
- "any DT_ entry.\n",
- source->name,
- sname);
- }
- else {
- INFO("Section [%s] was removed, not matching it to dynamic "
- "ranges.\n",
- sname);
- }
- } /* for ... */
-
- if (source->rel.sections) sort_ranges(source->rel.sections);
- if (source->jmprel.sections) sort_ranges(source->jmprel.sections);
-}
-
-static void drop_sections(source_t *source)
-{
- INFO("We are dropping some sections from [%s]--creating section entries "
- "only for remaining sections.\n",
- source->name);
- /* Renumber the sections. The numbers for the sections after those we are
- dropping will be shifted back by the number of dropped sections. */
- int cnt, idx;
- for (cnt = idx = 1; cnt < source->shnum; ++cnt) {
- if (source->shdr_info[cnt].idx > 0) {
- source->shdr_info[cnt].idx = idx++;
-
- /* Create a new section. */
- FAILIF_LIBELF((source->shdr_info[cnt].newscn =
- elf_newscn(source->elf)) == NULL, elf_newscn);
- ASSERT(elf_ndxscn (source->shdr_info[cnt].newscn) ==
- source->shdr_info[cnt].idx);
-
- /* Copy the section data */
- Elf_Data *olddata =
- elf_getdata(source->shdr_info[cnt].scn, // old section
- NULL);
- FAILIF_LIBELF(NULL == olddata, elf_getdata);
- Elf_Data *data =
- elf_newdata(source->shdr_info[cnt].newscn);
- FAILIF_LIBELF(NULL == data, elf_newdata);
- *data = *olddata;
-#if COPY_SECTION_DATA_BUFFER
- if (olddata->d_buf != NULL) {
- data->d_buf = MALLOC(data->d_size);
- memcpy(data->d_buf, olddata->d_buf, olddata->d_size);
- }
-#endif
- source->shdr_info[cnt].data = data;
-
- if (data->d_size !=
- source->shdr_info[cnt].shdr.sh_size) {
- INFO("Trimming new-section data from %d to %lld bytes "
- "(as calculated by adjust_dynamic_segment()).\n",
- data->d_size,
- source->shdr_info[cnt].shdr.sh_size);
- data->d_size =
- source->shdr_info[cnt].shdr.sh_size;
- }
-
- INFO("\tsection [%s] (old offset %lld, old size %lld) "
- "will have index %d (was %d), new size %d\n",
- source->shdr_info[cnt].name,
- source->shdr_info[cnt].old_shdr.sh_offset,
- source->shdr_info[cnt].old_shdr.sh_size,
- source->shdr_info[cnt].idx,
- elf_ndxscn(source->shdr_info[cnt].scn),
- data->d_size);
- } else {
- INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %d), "
- "it will be discarded.\n",
- source->shdr_info[cnt].name,
- source->shdr_info[cnt].shdr.sh_offset,
- source->shdr_info[cnt].shdr.sh_size,
- elf_ndxscn(source->shdr_info[cnt].scn));
- }
-
- /* NOTE: We mark use_old_shdr_for_relocation_calculations even for the
- sections we are removing. adjust_elf has an assertion that makes
- sure that if the values for the size of a section according to its
- header and its data structure differ, then we are using explicitly
- the old section header for calculations, and that the section in
- question is a relocation section.
- */
- source->shdr_info[cnt].use_old_shdr_for_relocation_calculations = true;
- } /* for */
-}
-
-static source_t* process_file(const char *filename,
- const char *output, int is_file,
- void (*report_library_size_in_memory)(
- const char *name, off_t fsize),
- unsigned (*get_next_link_address)(
- const char *name),
- int locals_only,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs,
- char **default_libs,
- int num_default_libs,
- int dry_run,
- int *total_num_handled_relocs,
- int *total_num_unhandled_relocs)
-{
- /* Look up the file in the list of already-handles files, which are
- represented by source_t structs. If we do not find the file, then we
- haven't prelinked it yet. If we find it, then we have, so we do
- nothing. Keep in mind that apriori operates on an entire collection
- of files, and if application A used library L, and so does application
- B, if we process A first, then by the time we get to B we will have
- prelinked L already; that's why we check first to see if a library has
- been prelinked.
- */
- source_t *source =
- find_source(filename, lib_lookup_dirs, num_lib_lookup_dirs);
- if (NULL == source) {
- /* If we could not find the source, then it hasn't been processed yet,
- so we go ahead and process it! */
- INFO("Processing [%s].\n", filename);
- char *full = find_file(filename, lib_lookup_dirs, num_lib_lookup_dirs);
- FAILIF(NULL == full,
- "Could not find [%s] in the current directory or in any of "
- "the search paths!\n", filename);
-
- unsigned base = get_next_link_address(full);
-
- source = init_source(full, output, is_file, base, dry_run);
-
- if (source == NULL) {
- INFO("File [%s] is a static executable.\n", filename);
- return NULL;
- }
- ASSERT(source->dynamic.scn != NULL);
-
- /* We need to increment the next prelink address only when the file we
- are currently handing is a shared library. Executables do not need
- to be prelinked at a different address, they are always at address
- zero.
-
- Also, if we are prelinking locals only, then we are handling a
- single file per invokation of apriori, so there is no need to
- increment the prelink address unless there is a global prelink map,
- in which case we do need to check to see if the library isn't
- running into its neighbouts in the prelink map.
- */
- if (source->oldelf_hdr.e_type != ET_EXEC &&
- (!locals_only ||
- report_library_size_in_memory ==
- pm_report_library_size_in_memory)) {
- /* This sets the next link address only if an increment was not
- specified by the user. If an address increment was specified,
- then we just check to make sure that the file size is less than
- the increment.
-
- NOTE: The file size is the absolute highest number of bytes that
- the file may occupy in memory, if the entire file is loaded, but
- this is almost next the case. A file will often have sections
- which are not loaded, which could add a lot of size. That's why
- we start off with the file size and then subtract the size of
- the biggest sections that will not get loaded, which are the
- varios DWARF sections, all of which of which are named starting
- with ".debug_".
-
- We could do better than this (by caculating exactly how many
- bytes from that file will be loaded), but that's an overkill.
- Unless the prelink-address increment becomes too small, the file
- size after subtracting the sizes of the DWARF section will be a
- good-enough upper bound.
- */
-
- unsigned long fsize = source->elf_file_info.st_size;
- INFO("Calculating loadable file size for next link address. "
- "Starting with %ld.\n", fsize);
- if (true) {
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr_mem, *shdr;
- const char *scn_name;
- while ((scn = elf_nextscn (source->oldelf, scn)) != NULL) {
- shdr = gelf_getshdr(scn, &shdr_mem);
- FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
- scn_name = elf_strptr (source->oldelf,
- source->shstrndx, shdr->sh_name);
- ASSERT(scn_name != NULL);
-
- if (!(shdr->sh_flags & SHF_ALLOC)) {
- INFO("\tDecrementing by %lld on account of section "
- "[%s].\n",
- shdr->sh_size,
- scn_name);
- fsize -= shdr->sh_size;
- }
- }
- }
- INFO("Done calculating loadable file size for next link address: "
- "Final value is %ld.\n", fsize);
- report_library_size_in_memory(source->name, fsize);
- }
-
- /* Identify the dynamic segment and process it. Specifically, we find
- out what dependencies, if any, this file has. Whenever we encounter
- such a dependency, we process it recursively; we find out where the
- various relocation information sections are stored. */
-
- size_t dynidx;
- GElf_Dyn *dyn, dyn_mem;
- size_t numdyn =
- source->dynamic.shdr.sh_size /
- source->dynamic.shdr.sh_entsize;
- ASSERT(source->dynamic.shdr.sh_size == source->dynamic.data->d_size);
-
- source->rel.idx = source->rel.sz_idx = -1;
- source->jmprel.idx = source->jmprel.sz_idx = -1;
-
- for (dynidx = 0; dynidx < numdyn; dynidx++) {
- dyn = gelf_getdyn (source->dynamic.data,
- dynidx,
- &dyn_mem);
- FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
- /* When we are processing only the local relocations in a file,
- we don't need to handle any of the dependencies. It won't
- hurt if we do, but we will be doing unnecessary work.
- */
- switch (dyn->d_tag)
- {
- case DT_NEEDED:
- if (!locals_only) {
- /* Process the needed library recursively.
- */
- const char *dep_lib =
-#if ELF_STRPTR_IS_BROKEN
- (((char *)elf_getdata(
- elf_getscn(source->elf,
- source->dynamic.shdr.sh_link),
- NULL)->d_buf) + dyn->d_un.d_val);
-#else
- elf_strptr (source->elf,
- source->dynamic.shdr.sh_link,
- dyn->d_un.d_val);
-#endif
- ASSERT(dep_lib != NULL);
- INFO("[%s] depends on [%s].\n", filename, dep_lib);
- ASSERT(output == NULL || is_file == 0);
- source_t *dep = process_file(dep_lib,
- output, is_file,
- report_library_size_in_memory,
- get_next_link_address,
- locals_only,
- lib_lookup_dirs,
- num_lib_lookup_dirs,
- default_libs,
- num_default_libs,
- dry_run,
- total_num_handled_relocs,
- total_num_unhandled_relocs);
-
- /* Add the library to the dependency list. */
- if (source->num_lib_deps == source->lib_deps_size) {
- source->lib_deps_size += 10;
- source->lib_deps = REALLOC(source->lib_deps,
- source->lib_deps_size *
- sizeof(source_t *));
- }
- source->lib_deps[source->num_lib_deps++] = dep;
- }
- break;
- case DT_JMPREL:
- source->jmprel.idx = dynidx;
- source->jmprel.addr = dyn->d_un.d_ptr;
- break;
- case DT_PLTRELSZ:
- source->jmprel.sz_idx = dynidx;
- source->jmprel.size = dyn->d_un.d_val;
- break;
- case DT_REL:
- source->rel.idx = dynidx;
- source->rel.addr = dyn->d_un.d_ptr;
- break;
- case DT_RELSZ:
- source->rel.sz_idx = dynidx;
- source->rel.size = dyn->d_un.d_val;
- break;
- case DT_RELA:
- case DT_RELASZ:
- FAILIF(1, "Can't handle DT_RELA and DT_RELASZ entries!\n");
- break;
- } /* switch */
- } /* for each dynamic entry... */
-
- INFO("Handling [%s].\n", filename);
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- if (!source->prelinked)
-#endif
- {
- /* When ADJUST_ELF is defined, this call to prelink is a dry run
- intended to calculate the number of relocations that could not
- be handled. This, in turn, allows us to calculate the amount by
- which we can shrink the various relocation sections before we
- call adjust_elf. After we've adjusted the sections, we will
- call prelink() one more time to do the actual work.
-
- NOTE: Even when ADJUST_ELF != 0, we cannot adjust an ELF file
- that is an executabe, because an executable is not PIC.
- */
-
- int num_unfinished_relocs = 0;
- bool adjust_file = ADJUST_ELF && source->elf_hdr.e_type != ET_EXEC;
- INFO("\n\n\tPRELINKING %s\n\n",
- adjust_file ?
- "(CALCULATE NUMBER OF HANDLED RELOCATIONS)" :
- "(ACTUAL)");
- int num_relocs = prelink(source, locals_only,
- adjust_file || dry_run,
- lib_lookup_dirs, num_lib_lookup_dirs,
- default_libs, num_default_libs,
- &num_unfinished_relocs);
- INFO("[%s]: (calculate changes) handled %d, could not handle %d "
- "relocations.\n",
- source->name,
- num_relocs,
- num_unfinished_relocs);
-
- if (adjust_file && !dry_run)
- {
- /* Find out the new section sizes of the relocation sections,
- but do not move any relocations around, because adjust_elf
- needs to know about all relocations in order to adjust the
- file correctly.
- */
- match_relocation_sections_to_dynamic_ranges(source);
-
- /* We haven't set up source->shdr_info[] yet, so we do it now.
-
- NOTE: setup_shdr_info() depends only on source->oldelf, not
- on source->elf! source->elf is not even defined yet. We
- initialize source->shdr_info[] based on the section
- information of the unmodified ELF file, and then make our
- modifications in the call to adjust_dynamic_segment() based
- on this information. adjust_dynamic_segment() will
- rearrange the unhandled relocations in the beginning of
- their relocation sections, and adjust the size of those
- relocation sections. In the case when a relocation section
- is completely handled, adjust_dynamic_segment() will mark it
- for removal by function adjust_elf.
- */
-
- ASSERT(source->elf == source->oldelf);
- ASSERT(source->shdr_info == NULL);
- setup_shdr_info(source);
- ASSERT(source->shdr_info != NULL);
-
- INFO("\n\n\tADJUSTING DYNAMIC SEGMENT "
- "(CALCULATE CHANGES)\n\n");
- bool drop_some_sections = adjust_dynamic_segment(source, true);
-
- /* Reopen the elf file! Note that we are not doing a dry run
- (the if statement above makes sure of that.)
-
- NOTE: We call init_elf() after we called
- adjust_dynamic_segment() in order to have
- adjust_dynamic_segment() refer to source->oldelf when
- it refers to source->elf. Since
- adjust_dynamic_segment doesn't actually write to the
- ELF file, this is OK. adjust_dynamic_segment()
- updates the sh_size fields of saved section headers
- and optionally marks sections for removal.
-
- Having adjust_dynamic_segment() refer to
- source->oldelf means that we'll have access to
- section-name strings so we can print them out in our
- logging and debug output.
- */
- source->elf = init_elf(source, false);
-
- /* This is the same code as in init_source() after the call to
- * init_elf(). */
- ASSERT(source->elf != source->oldelf);
- ebl_closebackend(source->ebl);
- source->ebl = ebl_openbackend (source->elf);
- FAILIF_LIBELF(NULL == source->ebl, ebl_openbackend);
-#ifdef ARM_SPECIFIC_HACKS
- FAILIF_LIBELF(0 != arm_init(source->elf,
- source->elf_hdr.e_machine,
- source->ebl, sizeof(Ebl)),
- arm_init);
-#endif/*ARM_SPECIFIC_HACKS*/
-
- if (drop_some_sections)
- drop_sections(source);
- else {
- INFO("All sections remain in [%s]--we are changing at "
- "most section sizes.\n", source->name);
- create_elf_sections(source, NULL);
- int cnt, idx;
- for (cnt = idx = 1; cnt < source->shnum; ++cnt) {
- Elf_Data *data = elf_getdata(
- source->shdr_info[cnt].newscn, // new section
- NULL);
- if (data->d_size !=
- source->shdr_info[cnt].shdr.sh_size) {
- INFO("Trimming new-section data from %d to %lld "
- "bytes (as calculated by "
- "adjust_dynamic_segment()).\n",
- data->d_size,
- source->shdr_info[cnt].shdr.sh_size);
- data->d_size = source->shdr_info[cnt].shdr.sh_size;
- }
- }
- }
-
- /* Shrink it! */
- INFO("\n\n\tADJUSTING ELF\n\n");
- adjust_elf(
- source->oldelf, source->name,
- source->elf, source->name,
- source->ebl,
- &source->old_ehdr_mem,
- NULL, 0, // no symbol filter
- source->shdr_info, // information on how to adjust the ELF
- source->shnum, // length of source->shdr_info[]
- source->phdr_info, // program-header info
- source->shnum, // irrelevant--we're not rebuilding shstrtab
- source->shnum, // number of sections in file
- source->shstrndx, // index of shstrtab (both in
- // shdr_info[] and as a section index)
- NULL, // irrelevant, since we are not rebuilding shstrtab
- drop_some_sections, // some sections are being dropped
- elf_ndxscn(source->dynamic.scn), // index of .dynamic
- elf_ndxscn(source->symtab.scn), // index of .dynsym
- 1, // allow shady business
- &source->shstrtab_data,
- true,
- false); // do not rebuild shstrtab
-
- INFO("\n\n\tREINITIALIZING STRUCTURES "
- "(TO CONTAIN ADJUSTMENTS)\n\n");
- reinit_source(source);
-
- INFO("\n\n\tPRELINKING (ACTUAL)\n\n");
-#ifdef DEBUG
- int old_num_unfinished_relocs = num_unfinished_relocs;
-#endif
- num_unfinished_relocs = 0;
-#ifdef DEBUG
- int num_relocs_take_two =
-#endif
- prelink(source, locals_only,
- false, /* not a dry run */
- lib_lookup_dirs, num_lib_lookup_dirs,
- default_libs, num_default_libs,
- &num_unfinished_relocs);
-
- /* The numbers for the total number of relocations and the
- number of unhandled relocations between the first and second
- invokationof prelink() must be the same! The first time we
- ran prelink() just to calculate the numbers so that we could
- calculate the adjustments to pass to adjust_elf, and the
- second time we actually carry out the prelinking; the
- numbers must stay the same!
- */
- ASSERT(num_relocs == num_relocs_take_two);
- ASSERT(old_num_unfinished_relocs == num_unfinished_relocs);
-
- INFO("[%s]: (actual prelink) handled %d, could not "
- "handle %d relocations.\n",
- source->name,
- num_relocs,
- num_unfinished_relocs);
- } /* if (adjust_elf && !dry_run) */
-
- *total_num_handled_relocs += num_relocs;
- *total_num_unhandled_relocs += num_unfinished_relocs;
-
- if(num_unfinished_relocs != 0 &&
- source->elf_hdr.e_type != ET_EXEC &&
- !locals_only)
- {
- /* One reason you could have unfinished relocations in an
- executable file is if this file used dlopen() and friends.
- We do not adjust relocation entries to those symbols,
- because libdl is a dummy only--the real functions are
- provided for by the dynamic linker itsef.
-
- NOTE FIXME HACK: This is specific to the Android dynamic
- linker, and may not be true in other cases.
- */
- PRINT("WARNING: Expecting to have unhandled relocations only "
- "for executables (%s is not an executable)!\n",
- source->name);
- }
-
- match_relocation_sections_to_dynamic_ranges(source);
-
- /* Now, for each relocation section, check to see if its address
- matches one of the DT_DYNAMIC relocation pointers. If so, then
- if the section has no unhandled relocations, simply set the
- associated DT_DYNAMIC entry's size to zero. If the section does
- have unhandled entries, then lump them all together at the front
- of the respective section and update the size of the respective
- DT_DYNAMIC entry to the new size of the section. A better
- approach would be do delete a relocation section if it has been
- fully relocated and to remove its entry from the DT_DYNAMIC
- array, and for relocation entries that still have some
- relocations in them, we should shrink the section if that won't
- violate relative offsets. This is more work, however, and for
- the speed improvement we expect from a prelinker, just patching
- up DT_DYNAMIC will suffice.
-
- Note: adjust_dynamic_segment() will modify source->shdr_info[]
- to denote any change in a relocation section's size. This
- will be picked up by adjust_elf, which will rearrange the
- file to eliminate the gap created by the decrease in size
- of the relocation section. We do not need to do this, but
- the relocation section could be large, and reduced
- drastically by the prelinking process, so it pays to
- adjust the file.
- */
-
- INFO("\n\n\tADJUSTING DYNAMIC SEGMENT (ACTUAL)\n\n");
- adjust_dynamic_segment(source, false);
- }
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- else INFO("[%s] is already prelinked at 0x%08lx.\n",
- filename,
- source->prelink_base);
-#endif
- } else INFO("[%s] has been processed already.\n", filename);
-
- return source;
-}
-
-void apriori(char **execs, int num_execs,
- char *output,
- void (*report_library_size_in_memory)(
- const char *name, off_t fsize),
- int (*get_next_link_address)(const char *name),
- int locals_only,
- int dry_run,
- char **lib_lookup_dirs, int num_lib_lookup_dirs,
- char **default_libs, int num_default_libs,
- char *mapfile)
-{
- source_t *source; /* for general usage */
- int input_idx;
-
- ASSERT(report_library_size_in_memory != NULL);
- ASSERT(get_next_link_address != NULL);
-
- /* Process and prelink each executable and object file. Function
- process_file() is called for each executable in the loop below.
- It calls itself recursively for each library. We prelink each library
- after prelinking its dependencies. */
- int total_num_handled_relocs = 0, total_num_unhandled_relocs = 0;
- for (input_idx = 0; input_idx < num_execs; input_idx++) {
- INFO("executable: [%s]\n", execs[input_idx]);
- /* Here process_file() is actually processing the top-level
- executable files. */
- process_file(execs[input_idx], output, num_execs == 1,
- report_library_size_in_memory,
- get_next_link_address, /* executables get a link address
- of zero, regardless of this
- value */
- locals_only,
- lib_lookup_dirs, num_lib_lookup_dirs,
- default_libs, num_default_libs,
- dry_run,
- &total_num_handled_relocs,
- &total_num_unhandled_relocs);
- /* if source is NULL, then the respective executable is static */
- /* Mark the source as an executable */
- } /* for each input executable... */
-
- PRINT("Handled %d relocations.\n", total_num_handled_relocs);
- PRINT("Could not handle %d relocations.\n", total_num_unhandled_relocs);
-
- /* We are done! Since the end result of our calculations is a set of
- symbols for each library that other libraries or executables link
- against, we iterate over the set of libraries one last time, and for
- each symbol that is marked as satisfying some dependence, we emit
- a line with the symbol's name to a text file derived from the library's
- name by appending the suffix .syms to it. */
-
- if (mapfile != NULL) {
- const char *mapfile_name = mapfile;
- FILE *fp;
- if (*mapfile == '+') {
- mapfile_name = mapfile + 1;
- INFO("Opening map file %s for append/write.\n",
- mapfile_name);
- fp = fopen(mapfile_name, "a");
- }
- else fp = fopen(mapfile_name, "w");
-
- FAILIF(fp == NULL, "Cannot open file [%s]: %s (%d)!\n",
- mapfile_name,
- strerror(errno),
- errno);
- source = sources;
- while (source) {
- /* If it's a library, print the results. */
- if (source->elf_hdr.e_type == ET_DYN) {
- /* Add to the memory map file. */
- fprintf(fp, "%s 0x%08lx %lld\n",
- basename(source->name),
- source->base,
- source->elf_file_info.st_size);
- }
- source = source->next;
- }
- fclose(fp);
- }
-
- /* Free the resources--you can't do it in the loop above because function
- print_symbol_references() accesses nodes other than the one being
- iterated over.
- */
- source = sources;
- while (source) {
- source_t *old = source;
- source = source->next;
- /* Destroy the evidence. */
- destroy_source(old);
- }
-}
diff --git a/tools/apriori/apriori.h b/tools/apriori/apriori.h
deleted file mode 100644
index 5e396fd..0000000
--- a/tools/apriori/apriori.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef LSD_H
-#define LSD_H
-
-void apriori(char **execs, int num_execs,
- char *output,
- void (*set_next_link_address)(const char *name, off_t fsize),
- int (*get_next_link_address)(const char *name),
- int locals_only,
- int dry_run,
- char **lib_lookup_dirs, int num_lib_lookup_dirs,
- char **default_libs, int num_default_libs,
- char *mapfile);
-
-#endif
diff --git a/tools/apriori/cmdline.c b/tools/apriori/cmdline.c
deleted file mode 100644
index 95f112a..0000000
--- a/tools/apriori/cmdline.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <debug.h>
-#include <cmdline.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <ctype.h>
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-static struct option long_options[] = {
- {"start-address", required_argument, 0, 's'},
- {"inc-address", required_argument, 0, 'i'},
- {"locals-only", no_argument, 0, 'l'},
- {"quiet", no_argument, 0, 'Q'},
- {"noupdate", no_argument, 0, 'n'},
- {"lookup", required_argument, 0, 'L'},
- {"default", required_argument, 0, 'D'},
- {"verbose", no_argument, 0, 'V'},
- {"help", no_argument, 0, 'h'},
- {"mapfile", required_argument, 0, 'M'},
- {"output", required_argument, 0, 'o'},
- {"prelinkmap", required_argument, 0, 'p'},
- {0, 0, 0, 0},
-};
-
-/* This array must parallel long_options[] */
-static const char *descriptions[] = {
- "start address to prelink libraries to",
- "address increment for each library",
- "prelink local relocations only",
- "suppress informational and non-fatal error messages",
- "do a dry run--calculate the prelink info but do not update any files",
- "provide a directory for library lookup",
- "provide a default library or executable for symbol lookup",
- "print verbose output",
- "print help screen",
- "print a list of prelink addresses to file (prefix filename with + to append instead of overwrite)",
- "specify an output directory (if multiple inputs) or file (is single input)",
- "specify a file with prelink addresses instead of a --start-address/--inc-address combination",
-};
-
-void print_help(const char *name) {
- fprintf(stdout,
- "invokation:\n"
- "\t%s file1 [file2 file3 ...] -Ldir1 [-Ldir2 ...] -saddr -iinc [-Vqn] [-M<logfile>]\n"
- "\t%s -l file [-Vqn] [-M<logfile>]\n"
- "\t%s -h\n\n", name, name, name);
- fprintf(stdout, "options:\n");
- struct option *opt = long_options;
- const char **desc = descriptions;
- while (opt->name) {
- fprintf(stdout, "\t-%c/--%s%s: %s\n",
- opt->val,
- opt->name,
- (opt->has_arg ? " (argument)" : ""),
- *desc);
- opt++;
- desc++;
- }
-}
-
-int get_options(int argc, char **argv,
- int *start_addr,
- int *inc_addr,
- int *locals_only,
- int *quiet,
- int *dry_run,
- char ***dirs,
- int *num_dirs,
- char ***defaults,
- int *num_defaults,
- int *verbose,
- char **mapfile,
- char **output,
- char **prelinkmap) {
- int c;
-
- ASSERT(dry_run); *dry_run = 0;
- ASSERT(quiet); *quiet = 0;
- ASSERT(verbose); *verbose = 0;
- ASSERT(dirs); *dirs = NULL;
- ASSERT(num_dirs); *num_dirs = 0;
- ASSERT(defaults); *defaults = NULL;
- ASSERT(num_defaults); *num_defaults = 0;
- ASSERT(start_addr); *start_addr = -1;
- ASSERT(inc_addr); *inc_addr = -1;
- ASSERT(locals_only); *locals_only = 0;
- ASSERT(mapfile); *mapfile = NULL;
- ASSERT(output); *output = NULL;
- ASSERT(prelinkmap); *prelinkmap = NULL;
- int dirs_size = 0;
- int defaults_size = 0;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long (argc, argv,
- "VhnQlL:D:s:i:M:o:p:",
- long_options,
- &option_index);
- /* Detect the end of the options. */
- if (c == -1) break;
-
- if (isgraph(c)) {
- INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
- }
-
-#define SET_STRING_OPTION(name) do { \
- ASSERT(optarg); \
- (*name) = strdup(optarg); \
-} while(0)
-
-#define SET_REPEATED_STRING_OPTION(arr, num, size) do { \
- if (*num == size) { \
- size += 10; \
- *arr = (char **)REALLOC(*arr, size * sizeof(char *)); \
- } \
- SET_STRING_OPTION(((*arr) + *num)); \
- (*num)++; \
-} while(0)
-
-#define SET_INT_OPTION(val) do { \
- ASSERT(optarg); \
- if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
- FAILIF(1 != sscanf(optarg+2, "%x", val), \
- "Expecting a hexadecimal argument!\n"); \
- } else { \
- FAILIF(1 != sscanf(optarg, "%d", val), \
- "Expecting a decimal argument!\n"); \
- } \
-} while(0)
-
- switch (c) {
- case 0:
- /* If this option set a flag, do nothing else now. */
- if (long_options[option_index].flag != 0)
- break;
- INFO ("option %s", long_options[option_index].name);
- if (optarg)
- INFO (" with arg %s", optarg);
- INFO ("\n");
- break;
- case 'Q': *quiet = 1; break;
- case 'n': *dry_run = 1; break;
- case 'M':
- SET_STRING_OPTION(mapfile);
- break;
- case 'o':
- SET_STRING_OPTION(output);
- break;
- case 'p':
- SET_STRING_OPTION(prelinkmap);
- break;
- case 's':
- SET_INT_OPTION(start_addr);
- break;
- case 'i':
- SET_INT_OPTION(inc_addr);
- break;
- case 'L':
- SET_REPEATED_STRING_OPTION(dirs, num_dirs, dirs_size);
- break;
- case 'D':
- SET_REPEATED_STRING_OPTION(defaults, num_defaults, defaults_size);
- break;
- case 'l': *locals_only = 1; break;
- case 'h': print_help(argv[0]); exit(1); break;
- case 'V': *verbose = 1; break;
- case '?':
- /* getopt_long already printed an error message. */
- break;
-
-#undef SET_STRING_OPTION
-#undef SET_REPEATED_STRING_OPTION
-#undef SET_INT_OPTION
-
- default:
- FAILIF(1, "Unknown option");
- }
- }
-
- return optind;
-}
diff --git a/tools/apriori/cmdline.h b/tools/apriori/cmdline.h
deleted file mode 100644
index 8f7f394..0000000
--- a/tools/apriori/cmdline.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef CMDLINE_H
-#define CMDLINE_H
-
-void print_help(const char *executable_name);
-
-int get_options(int argc, char **argv,
- int *start_addr,
- int *addr_increment,
- int *locals_only,
- int *quiet,
- int *dry_run,
- char ***dirs,
- int *num_dirs,
- char ***defaults,
- int *num_defaults,
- int *verbose,
- char **mapfile,
- char **output,
- char **prelinkmap);
-
-#endif/*CMDLINE_H*/
diff --git a/tools/apriori/common.h b/tools/apriori/common.h
deleted file mode 100644
index f5d9d2e..0000000
--- a/tools/apriori/common.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <libelf.h>
-#include <elf.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
-
-static inline int is_host_little(void)
-{
- short val = 0x10;
- return ((char *)&val)[0] != 0;
-}
-
-static inline long switch_endianness(long val)
-{
- long newval;
- ((char *)&newval)[3] = ((char *)&val)[0];
- ((char *)&newval)[2] = ((char *)&val)[1];
- ((char *)&newval)[1] = ((char *)&val)[2];
- ((char *)&newval)[0] = ((char *)&val)[3];
- return newval;
-}
-
-#endif/*COMMON_H*/
diff --git a/tools/apriori/debug.c b/tools/apriori/debug.c
deleted file mode 100644
index 263e09f..0000000
--- a/tools/apriori/debug.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <debug.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#define NUM_COLS (32)
-
-int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) {
- int num_nonprintable = 0;
- int i, last;
- char *pchr = (char *)b;
- fputc('\n', s);
- fprintf(s, "%p: ", b);
- for (i = last = 0; i < len; i++) {
- if (!elsize) {
- if (i && !(i % 4)) fprintf(s, " ");
- if (i && !(i % 8)) fprintf(s, " ");
- } else {
- if (i && !(i % elsize)) fprintf(s, " ");
- }
-
- if (i && !(i % NUM_COLS)) {
- while (last < i) {
- if (isprint(pchr[last]))
- fputc(pchr[last], s);
- else {
- fputc('.', s);
- num_nonprintable++;
- }
- last++;
- }
- fprintf(s, " (%d)\n%p: ", i, b);
- }
- fprintf(s, "%02x", (unsigned char)pchr[i]);
- }
- if (i && (i % NUM_COLS)) fputs("\n", s);
- return num_nonprintable;
-}
-
diff --git a/tools/apriori/debug.h b/tools/apriori/debug.h
deleted file mode 100644
index 3996898..0000000
--- a/tools/apriori/debug.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common.h>
-
-#ifdef DEBUG
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
- #define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
- #define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size) {
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size) {
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr) {
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr) {
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR PRINT
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/tools/apriori/hash.c b/tools/apriori/hash.c
deleted file mode 100644
index 9f1a614..0000000
--- a/tools/apriori/hash.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <hash.h>
-#include <string.h>
-
-int hash_lookup(Elf *elf,
- Elf_Data *hash,
- Elf_Data *symtab,
- Elf_Data *symstr,
- const char *symname) {
- Elf32_Word *hash_data = (Elf32_Word *)hash->d_buf;
- Elf32_Word index;
- Elf32_Word nbuckets = *hash_data++;
- Elf32_Word *buckets = ++hash_data;
- Elf32_Word *chains = hash_data + nbuckets;
-
- index = buckets[elf_hash(symname) % nbuckets];
- while (index != STN_UNDEF &&
- strcmp((char *)symstr->d_buf +
- ((Elf32_Sym *)symtab->d_buf)[index].st_name,
- symname)) {
- index = chains[index];
- }
-
- return index;
-}
diff --git a/tools/apriori/hash.h b/tools/apriori/hash.h
deleted file mode 100644
index af29b9e..0000000
--- a/tools/apriori/hash.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef HASH_H
-#define HASH_H
-
-#include <common.h>
-#include <libelf.h>
-#include <gelf.h>
-
-int hash_lookup(Elf *elf,
- Elf_Data *hash,
- Elf_Data *symtab,
- Elf_Data *symstr,
- const char *symname);
-
-#endif/*HASH_H*/
diff --git a/tools/apriori/main.c b/tools/apriori/main.c
deleted file mode 100644
index 552392a..0000000
--- a/tools/apriori/main.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* TODO:
- 1. check the ARM EABI version--this works for versions 1 and 2.
- 2. use a more-intelligent approach to finding the symbol table,
- symbol-string table, and the .dynamic section.
- 3. fix the determination of the host and ELF-file endianness
- 4. write the help screen
-*/
-
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <elf.h>
-#include <gelf.h>
-#include <cmdline.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <apriori.h>
-#include <prelinkmap.h>
-
-/* Flag set by --verbose. This variable is global as it is accessed by the
- macro INFO() in multiple compilation unites. */
-int verbose_flag = 0;
-/* Flag set by --quiet. This variable is global as it is accessed by the
- macro PRINT() in multiple compilation unites. */
-int quiet_flag = 0;
-static void print_dynamic_symbols(Elf *elf, const char *symtab_name);
-
-static unsigned s_next_link_addr;
-static off_t s_addr_increment;
-
-static void report_library_size_in_memory(const char *name, off_t fsize)
-{
- ASSERT(s_next_link_addr != -1UL);
- INFO("Setting next link address (current is at 0x%08x):\n",
- s_next_link_addr);
- if (s_addr_increment) {
- FAILIF(s_addr_increment < fsize,
- "Command-line-specified address increment of 0x%08llx (%lld) "
- "less than file [%s]'s size of %lld bytes!\n",
- s_addr_increment, s_addr_increment, name, fsize);
- FAILIF(s_next_link_addr % 4096,
- "User-provided address increment 0x%08lx "
- "is not page-aligned!\n",
- s_addr_increment);
- INFO("\tignoring file size, adjusting by address increment.\n");
- s_next_link_addr += s_addr_increment;
- }
- else {
- INFO("\tuser address increment is zero, adjusting by file size.\n");
- s_next_link_addr += fsize;
- s_next_link_addr &= ~(4096 - 1);
- }
- INFO("\t[%s] file size 0x%08lx\n",
- name,
- fsize);
- INFO("\tnext prelink address: 0x%08x\n", s_next_link_addr);
- ASSERT(!(s_next_link_addr % 4096)); /* New address must be page-aligned */
-}
-
-static unsigned get_next_link_address(const char *name) {
- return s_next_link_addr;
-}
-
-int main(int argc, char **argv) {
- /* Do not issue INFO() statements before you call get_options() to set
- the verbose flag as necessary.
- */
-
- char **lookup_dirs, **default_libs;
- char *mapfile, *output, *prelinkmap;
- int start_addr, inc_addr, locals_only, num_lookup_dirs,
- num_default_libs, dry_run;
- int first = get_options(argc, argv,
- &start_addr, &inc_addr, &locals_only,
- &quiet_flag,
- &dry_run,
- &lookup_dirs, &num_lookup_dirs,
- &default_libs, &num_default_libs,
- &verbose_flag,
- &mapfile,
- &output,
- &prelinkmap);
-
- /* Perform some command-line-parameter checks. */
- int cmdline_err = 0;
- if (first == argc) {
- ERROR("You must specify at least one input ELF file!\n");
- cmdline_err++;
- }
- /* We complain when the user does not specify a start address for
- prelinking when the user does not pass the locals_only switch. The
- reason is that we will have a collection of executables, which we always
- prelink to zero, and shared libraries, which we prelink at the specified
- prelink address. When the user passes the locals_only switch, we do not
- fail if the user does not specify start_addr, because the file to
- prelink may be an executable, and not a shared library. At this moment,
- we do not know what the case is. We find that out when we call function
- init_source().
- */
- if (!locals_only && start_addr == -1) {
- ERROR("You must specify --start-addr!\n");
- cmdline_err++;
- }
- if (start_addr == -1 && inc_addr != -1) {
- ERROR("You must provide a start address if you provide an "
- "address increment!\n");
- cmdline_err++;
- }
- if (prelinkmap != NULL && start_addr != -1) {
- ERROR("You may not provide a prelink-map file (-p) and use -s/-i "
- "at the same time!\n");
- cmdline_err++;
- }
- if (inc_addr == 0) {
- ERROR("You may not specify a link-address increment of zero!\n");
- cmdline_err++;
- }
- if (locals_only) {
- if (argc - first == 1) {
- if (inc_addr != -1) {
- ERROR("You are prelinking a single file; there is no point in "
- "specifying a prelink-address increment!\n");
- /* This is nonfatal error, but paranoia is healthy. */
- cmdline_err++;
- }
- }
- if (lookup_dirs != NULL || default_libs != NULL) {
- ERROR("You are prelinking local relocations only; there is "
- "no point in specifying lookup directories!\n");
- /* This is nonfatal error, but paranoia is healthy. */
- cmdline_err++;
- }
- }
-
- /* If there is an output option, then that must specify a file, if there is
- a single input file, or a directory, if there are multiple input
- files. */
- if (output != NULL) {
- struct stat output_st;
- FAILIF(stat(output, &output_st) < 0 && errno != ENOENT,
- "stat(%s): %s (%d)\n",
- output,
- strerror(errno),
- errno);
-
- if (argc - first == 1) {
- FAILIF(!errno && !S_ISREG(output_st.st_mode),
- "you have a single input file: -o must specify a "
- "file name!\n");
- }
- else {
- FAILIF(errno == ENOENT,
- "you have multiple input files: -o must specify a "
- "directory name, but %s does not exist!\n",
- output);
- FAILIF(!S_ISDIR(output_st.st_mode),
- "you have multiple input files: -o must specify a "
- "directory name, but %s is not a directory!\n",
- output);
- }
- }
-
- if (cmdline_err) {
- print_help(argv[0]);
- FAILIF(1, "There are command-line-option errors.\n");
- }
-
- /* Check to see whether the ELF library is current. */
- FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n");
-
- if (inc_addr < 0) {
- if (!locals_only)
- PRINT("User has not provided an increment address, "
- "will use library size to calculate successive "
- "prelink addresses.\n");
- inc_addr = 0;
- }
-
- void (*func_report_library_size_in_memory)(const char *name, off_t fsize);
- unsigned (*func_get_next_link_address)(const char *name);
-
- if (prelinkmap != NULL) {
- INFO("Reading prelink addresses from prelink-map file [%s].\n",
- prelinkmap);
- pm_init(prelinkmap);
- func_report_library_size_in_memory = pm_report_library_size_in_memory;
- func_get_next_link_address = pm_get_next_link_address;
- }
- else {
- INFO("Start address: 0x%x\n", start_addr);
- INFO("Increment address: 0x%x\n", inc_addr);
- s_next_link_addr = start_addr;
- s_addr_increment = inc_addr;
- func_report_library_size_in_memory = report_library_size_in_memory;
- func_get_next_link_address = get_next_link_address;
- }
-
- /* Prelink... */
- apriori(&argv[first], argc - first, output,
- func_report_library_size_in_memory, func_get_next_link_address,
- locals_only,
- dry_run,
- lookup_dirs, num_lookup_dirs,
- default_libs, num_default_libs,
- mapfile);
-
- FREEIF(mapfile);
- FREEIF(output);
- if (lookup_dirs) {
- ASSERT(num_lookup_dirs);
- while (num_lookup_dirs--)
- FREE(lookup_dirs[num_lookup_dirs]);
- FREE(lookup_dirs);
- }
- if (default_libs) {
- ASSERT(num_default_libs);
- while (num_default_libs--)
- FREE(default_libs[num_default_libs]);
- FREE(default_libs);
- }
-
- return 0;
-}
diff --git a/tools/apriori/prelink_info.c b/tools/apriori/prelink_info.c
deleted file mode 100644
index da7ca05..0000000
--- a/tools/apriori/prelink_info.c
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include <prelink_info.h>
-#include <debug.h>
-#include <common.h>
-
-typedef struct {
- int32_t mmap_addr;
- char tag[4]; /* 'P', 'R', 'E', ' ' */
-} prelink_info_t __attribute__((packed));
-
-static inline void set_prelink(long *prelink_addr,
- int elf_little,
- prelink_info_t *info)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
- if (prelink_addr) {
- if (!(elf_little ^ is_host_little())) {
- /* Same endianness */
- *prelink_addr = info->mmap_addr;
- }
- else {
- /* Different endianness */
- *prelink_addr = switch_endianness(info->mmap_addr);
- }
- }
-}
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
- int fd = open(fname, O_RDONLY);
- FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
- fname, strerror(errno), errno);
- off_t end = lseek(fd, 0, SEEK_END);
-
- int nr = sizeof(prelink_info_t);
-
- off_t sz = lseek(fd, -nr, SEEK_CUR);
- ASSERT((long)(end - sz) == (long)nr);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- prelink_info_t info;
- int num_read = read(fd, &info, nr);
- FAILIF(num_read < 0,
- "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
- fd, strerror(errno), errno);
- FAILIF(num_read != sizeof(info),
- "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
- "expected (read %d)!\n",
- fd, sizeof(info), num_read);
-
- int prelinked = 0;
- if (!strncmp(info.tag, "PRE ", 4)) {
- set_prelink(prelink_addr, elf_little, &info);
- prelinked = 1;
- }
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
- return prelinked;
-}
-
-void setup_prelink_info(const char *fname, int elf_little, long base)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
- int fd = open(fname, O_WRONLY);
- FAILIF(fd < 0,
- "open(%s, O_WRONLY): %s (%d)\n" ,
- fname, strerror(errno), errno);
- prelink_info_t info;
- off_t sz = lseek(fd, 0, SEEK_END);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- if (!(elf_little ^ is_host_little())) {
- /* Same endianness */
- INFO("Host and ELF file [%s] have same endianness.\n", fname);
- info.mmap_addr = base;
- }
- else {
- /* Different endianness */
- INFO("Host and ELF file [%s] have different endianness.\n", fname);
- info.mmap_addr = switch_endianness(base);
- }
- strncpy(info.tag, "PRE ", 4);
-
- int num_written = write(fd, &info, sizeof(info));
- FAILIF(num_written < 0,
- "write(%d, &info, sizeof(info)): %s (%d)\n",
- fd, strerror(errno), errno);
- FAILIF(sizeof(info) != num_written,
- "Could not write %d bytes (wrote only %d bytes) as expected!\n",
- sizeof(info), num_written);
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
-}
-
-#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/
diff --git a/tools/apriori/prelink_info.h b/tools/apriori/prelink_info.h
deleted file mode 100644
index e2787cb..0000000
--- a/tools/apriori/prelink_info.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PRELINK_INFO_H
-#define PRELINK_INFO_H
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr);
-void setup_prelink_info(const char *fname, int elf_little, long base);
-
-#endif
-#endif/*PRELINK_INFO_H*/
diff --git a/tools/apriori/prelinkmap.c b/tools/apriori/prelinkmap.c
deleted file mode 100644
index 9fb00e4..0000000
--- a/tools/apriori/prelinkmap.c
+++ /dev/null
@@ -1,170 +0,0 @@
-#include <prelinkmap.h>
-#include <debug.h>
-#include <errno.h>
-#include <string.h>
-#include <libgen.h>
-#include <ctype.h>
-
-typedef struct mapentry mapentry;
-
-#define MAX_ALIASES 10
-
-struct mapentry
-{
- mapentry *next;
- unsigned base;
- char *names[MAX_ALIASES];
- int num_names;
-};
-
-static mapentry *maplist = 0;
-
-/* These values limit the address range within which we prelinked libraries
- reside. The limit is not set in stone, but should be observed in the
- prelink map, or the prelink step will fail.
-*/
-
-#define PRELINK_MIN 0x90000000
-#define PRELINK_MAX 0xBFFFFFFF
-
-void pm_init(const char *file)
-{
- unsigned line = 0;
- char buf[256];
- char *x;
- FILE *fp;
- mapentry *me;
- unsigned last = -1UL;
-
- fp = fopen(file, "r");
- FAILIF(fp == NULL, "Error opening file %s: %s (%d)\n",
- file, strerror(errno), errno);
-
- while(fgets(buf, 256, fp)){
- x = buf;
- line++;
-
- /* eat leading whitespace */
- while(isspace(*x)) x++;
-
- /* comment or blank line? skip! */
- if(*x == '#') continue;
- if(*x == 0) continue;
-
- /* skip name */
- while(*x && !isspace(*x)) x++;
-
- if(*x) {
- *x++ = 0;
- /* skip space before address */
- while(*x && isspace(*x)) x++;
- }
-
- /* no address? complain. */
- if(*x == 0) {
- fprintf(stderr,"warning: %s:%d no base address specified\n",
- file, line);
- continue;
- }
-
- if (isalpha(*x)) {
- /* Assume that this is an alias, and look through the list of
- already-installed libraries.
- */
- me = maplist;
- while(me) {
- /* The strlen() call ignores the newline at the end of x */
- if (!strncmp(me->names[0], x, strlen(me->names[0]))) {
- PRINT("Aliasing library %s to %s at %08x\n",
- buf, x, me->base);
- break;
- }
- me = me->next;
- }
- FAILIF(!me, "Nonexistent alias %s -> %s\n", buf, x);
- }
- else {
- unsigned n = strtoul(x, 0, 16);
- /* Note that this is not the only bounds check. If a library's
- size exceeds its slot as defined in the prelink map, the
- prelinker will exit with an error. See
- pm_report_library_size_in_memory().
- */
- FAILIF((n < PRELINK_MIN) || (n > PRELINK_MAX),
- "%s:%d base 0x%08x out of range.\n",
- file, line, n);
-
- me = malloc(sizeof(mapentry));
- FAILIF(me == NULL, "Out of memory parsing %s\n", file);
-
- FAILIF(last <= n, "The prelink map is not in descending order "
- "at entry %s (%08x)!\n", buf, n);
- last = n;
-
- me->base = n;
- me->next = maplist;
- me->num_names = 0;
- maplist = me;
- }
-
- FAILIF(me->num_names >= MAX_ALIASES,
- "Too many aliases for library %s, maximum is %d.\n",
- me->names[0],
- MAX_ALIASES);
- me->names[me->num_names] = strdup(buf);
- me->num_names++;
- }
-
- fclose(fp);
-}
-
-/* apriori() calls this function when it determine the size of a library
- in memory. pm_report_library_size_in_memory() makes sure that the library
- fits in the slot provided by the prelink map.
-*/
-void pm_report_library_size_in_memory(const char *name,
- off_t fsize)
-{
- char *x;
- mapentry *me;
- int n;
-
- x = strrchr(name,'/');
- if(x) name = x+1;
-
- for(me = maplist; me; me = me->next){
- for (n = 0; n < me->num_names; n++) {
- if(!strcmp(name, me->names[n])) {
- off_t slot = me->next ? me->next->base : PRELINK_MAX;
- slot -= me->base;
- FAILIF(fsize > slot,
- "prelink map error: library %s@0x%08x is too big "
- "at %lld bytes, it runs %lld bytes into "
- "library %s@0x%08x!\n",
- me->names[0], me->base, fsize, fsize - slot,
- me->next->names[0], me->next->base);
- return;
- }
- }
- }
-
- FAILIF(1, "library '%s' not in prelink map\n", name);
-}
-
-unsigned pm_get_next_link_address(const char *lookup_name)
-{
- char *x;
- mapentry *me;
- int n;
-
- x = strrchr(lookup_name,'/');
- if(x) lookup_name = x+1;
-
- for(me = maplist; me; me = me->next)
- for (n = 0; n < me->num_names; n++)
- if(!strcmp(lookup_name, me->names[n]))
- return me->base;
-
- FAILIF(1, "library '%s' not in prelink map\n", lookup_name);
- return 0;
-}
diff --git a/tools/apriori/prelinkmap.h b/tools/apriori/prelinkmap.h
deleted file mode 100644
index 17f7660..0000000
--- a/tools/apriori/prelinkmap.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef PRELINKMAP_H
-#define PRELINKMAP_H
-
-#include <sys/types.h>
-
-extern void pm_init(const char *file);
-extern void pm_report_library_size_in_memory(const char *name, off_t fsize);
-extern unsigned pm_get_next_link_address(const char *name);
-
-#endif/*PRELINKMAP_H*/
diff --git a/tools/apriori/rangesort.c b/tools/apriori/rangesort.c
deleted file mode 100644
index b0295e8..0000000
--- a/tools/apriori/rangesort.c
+++ /dev/null
@@ -1,317 +0,0 @@
-#include <common.h>
-#include <debug.h>
-#include <rangesort.h>
-
-#define PARALLEL_ARRAY_SIZE (5)
-
-struct range_list_t {
- range_t *array;
-#ifdef DEBUG
- int is_sorted;
-#endif
- int array_length;
- int num_ranges;
-};
-
-range_list_t* init_range_list(void) {
- range_list_t *ranges = (range_list_t *)MALLOC(sizeof(range_list_t));
-
- ranges->array = (range_t *)MALLOC(PARALLEL_ARRAY_SIZE*sizeof(range_t));
- ranges->array_length = PARALLEL_ARRAY_SIZE;
- ranges->num_ranges = 0;
-#ifdef DEBUG
- ranges->is_sorted = 0;
-#endif
- return ranges;
-}
-
-void destroy_range_list(range_list_t *ranges) {
- int idx;
- for (idx = 0; idx < ranges->num_ranges; idx++) {
- if (ranges->array[idx].user_dtor) {
- ASSERT(ranges->array[idx].user);
- ranges->array[idx].user_dtor(ranges->array[idx].user);
- }
- }
- FREE(ranges->array);
- FREE(ranges);
-}
-
-static inline int CONTAINS(range_t *container, range_t *contained) {
- return container->start <= contained->start && contained->length &&
- (container->start + container->length >
- contained->start + contained->length);
-}
-
-static inline int IN_RANGE(range_t *range, GElf_Off point) {
- return
- range->start <= point &&
- point < (range->start + range->length);
-}
-
-static inline int INTERSECT(range_t *left, range_t *right) {
- return
- (IN_RANGE(left, right->start) &&
- IN_RANGE(right, left->start + left->length)) ||
- (IN_RANGE(right, left->start) &&
- IN_RANGE(left, right->start + right->length));
-}
-
-static int range_cmp_for_search(const void *l, const void *r) {
- range_t *left = (range_t *)l, *right = (range_t *)r;
- if (INTERSECT(left, right) ||
- CONTAINS(left, right) ||
- CONTAINS(right, left)) {
- return 0;
- }
- return left->start - right->start;
-}
-
-static inline void run_checks(const void *l, const void *r) {
- range_t *left = (range_t *)l, *right = (range_t *)r;
- if (CONTAINS(left, right)) {
- if (left->err_fn)
- left->err_fn(ERROR_CONTAINS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld) contains [%lld, %lld)!\n",
- left->start, left->start + left->length,
- right->start, right->start + right->length);
- }
- if (CONTAINS(right, left)) {
- if (right->err_fn)
- right->err_fn(ERROR_CONTAINS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld) contains [%lld, %lld)!\n",
- right->start, right->start + right->length,
- left->start, left->start + left->length);
- }
- if (INTERSECT(left, right)) {
- if (left->err_fn)
- left->err_fn(ERROR_OVERLAPS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld)and [%lld, %lld) intersect!\n",
- left->start, left->start + left->length,
- right->start, right->start + right->length);
- }
-}
-
-static int range_cmp(const void *l, const void *r) {
- run_checks(l, r);
- range_t *left = (range_t *)l, *right = (range_t *)r;
- return left->start - right->start;
-}
-
-void add_unique_range_nosort(
- range_list_t *ranges,
- GElf_Off start,
- GElf_Off length,
- void *user,
- void (*err_fn)(range_error_t, range_t *, range_t *),
- void (*user_dtor)(void * ))
-{
- if (ranges->num_ranges == ranges->array_length) {
- ranges->array_length += PARALLEL_ARRAY_SIZE;
- ranges->array = REALLOC(ranges->array,
- ranges->array_length*sizeof(range_t));
- }
- ranges->array[ranges->num_ranges].start = start;
- ranges->array[ranges->num_ranges].length = length;
- ranges->array[ranges->num_ranges].user = user;
- ranges->array[ranges->num_ranges].err_fn = err_fn;
- ranges->array[ranges->num_ranges].user_dtor = user_dtor;
- ranges->num_ranges++;
-}
-
-range_list_t *sort_ranges(range_list_t *ranges) {
- if (ranges->num_ranges > 1)
- qsort(ranges->array, ranges->num_ranges, sizeof(range_t), range_cmp);
- ranges->is_sorted = 1;
- return ranges;
-}
-
-range_t *find_range(range_list_t *ranges, GElf_Off value) {
-#if 1
- int i;
- for (i = 0; i < ranges->num_ranges; i++) {
- if (ranges->array[i].start <= value &&
- value < ranges->array[i].start + ranges->array[i].length)
- return ranges->array + i;
- }
- return NULL;
-#else
- ASSERT(ranges->is_sorted); /* The range list must be sorted */
- range_t lookup;
- lookup.start = value;
- lookup.length = 0;
- return
- (range_t *)bsearch(&lookup,
- ranges->array, ranges->num_ranges, sizeof(range_t),
- range_cmp_for_search);
-#endif
-}
-
-int get_num_ranges(const range_list_t *ranges)
-{
- return ranges->num_ranges;
-}
-
-range_t *get_sorted_ranges(const range_list_t *ranges, int *num_ranges) {
- ASSERT(ranges->is_sorted); /* The range list must be sorted */
- if (num_ranges) {
- *num_ranges = ranges->num_ranges;
- }
- return ranges->array;
-}
-
-GElf_Off get_last_address(const range_list_t *ranges) {
- ASSERT(ranges->num_ranges);
- return
- ranges->array[ranges->num_ranges-1].start +
- ranges->array[ranges->num_ranges-1].length;
-}
-
-static void handle_range_error(range_error_t err,
- range_t *left, range_t *right) {
- switch (err) {
- case ERROR_CONTAINS:
- ERROR("ERROR: section (%lld, %lld bytes) contains "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- case ERROR_OVERLAPS:
- ERROR("ERROR: Section (%lld, %lld bytes) intersects "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- default:
- ASSERT(!"Unknown range error code!");
- }
-
- FAILIF(1, "Range error.\n");
-}
-
-static void destroy_contiguous_range_info(void *user) {
- contiguous_range_info_t *info = (contiguous_range_info_t *)user;
- FREE(info->ranges);
- FREE(info);
-}
-
-static void handle_contiguous_range_error(range_error_t err,
- range_t *left,
- range_t *right)
-{
- contiguous_range_info_t *left_data =
- (contiguous_range_info_t *)left->user;
- ASSERT(left_data);
- contiguous_range_info_t *right_data =
- (contiguous_range_info_t *)right->user;
- ASSERT(right_data);
-
- PRINT("Contiguous-range overlap error. Printing contained ranges:\n");
- int cnt;
- PRINT("\tLeft ranges:\n");
- for (cnt = 0; cnt < left_data->num_ranges; cnt++) {
- PRINT("\t\t[%lld, %lld)\n",
- left_data->ranges[cnt].start,
- left_data->ranges[cnt].start + left_data->ranges[cnt].length);
- }
- PRINT("\tRight ranges:\n");
- for (cnt = 0; cnt < right_data->num_ranges; cnt++) {
- PRINT("\t\t[%lld, %lld)\n",
- right_data->ranges[cnt].start,
- right_data->ranges[cnt].start + right_data->ranges[cnt].length);
- }
-
- handle_range_error(err, left, right);
-}
-
-range_list_t* get_contiguous_ranges(const range_list_t *input)
-{
- ASSERT(input);
- FAILIF(!input->is_sorted,
- "get_contiguous_ranges(): input range list is not sorted!\n");
-
- range_list_t* ret = init_range_list();
- int num_ranges;
- range_t *ranges = get_sorted_ranges(input, &num_ranges);
-
- int end_idx = 0;
- while (end_idx < num_ranges) {
- int start_idx = end_idx++;
- int old_end_idx = start_idx;
- int total_length = ranges[start_idx].length;
- while (end_idx < num_ranges) {
- if (ranges[old_end_idx].start + ranges[old_end_idx].length !=
- ranges[end_idx].start)
- break;
- old_end_idx = end_idx++;
- total_length += ranges[old_end_idx].length;
- }
-
- contiguous_range_info_t *user =
- (contiguous_range_info_t *)MALLOC(sizeof(contiguous_range_info_t));
- user->num_ranges = end_idx - start_idx;
- user->ranges = (range_t *)MALLOC(user->num_ranges * sizeof(range_t));
- int i;
- for (i = 0; i < end_idx - start_idx; i++)
- user->ranges[i] = ranges[start_idx + i];
- add_unique_range_nosort(ret,
- ranges[start_idx].start,
- total_length,
- user,
- handle_contiguous_range_error,
- destroy_contiguous_range_info);
- }
-
- return ret;
-}
-
-range_list_t* subtract_ranges(const range_list_t *r, const range_list_t *s)
-{
- ASSERT(r); ASSERT(r->is_sorted);
- ASSERT(s); ASSERT(s->is_sorted);
-
- range_list_t *result = init_range_list();
-
- int r_num_ranges, r_idx;
- range_t *r_ranges = get_sorted_ranges(r, &r_num_ranges);
- ASSERT(r_ranges);
-
- int s_num_ranges, s_idx;
- range_t *s_ranges = get_sorted_ranges(s, &s_num_ranges);
- ASSERT(s_ranges);
-
- s_idx = 0;
- for (r_idx = 0; r_idx < r_num_ranges; r_idx++) {
- GElf_Off last_start = r_ranges[r_idx].start;
- for (; s_idx < s_num_ranges; s_idx++) {
- if (CONTAINS(&r_ranges[r_idx], &s_ranges[s_idx])) {
- if (last_start ==
- r_ranges[r_idx].start + r_ranges[r_idx].length) {
- break;
- }
- if (last_start == s_ranges[s_idx].start) {
- last_start += s_ranges[s_idx].length;
- continue;
- }
- INFO("Adding subtracted range [%lld, %lld)\n",
- last_start,
- s_ranges[s_idx].start);
- add_unique_range_nosort(
- result,
- last_start,
- s_ranges[s_idx].start - last_start,
- NULL,
- NULL,
- NULL);
- last_start = s_ranges[s_idx].start + s_ranges[s_idx].length;
- } else {
- ASSERT(!INTERSECT(&r_ranges[r_idx], &s_ranges[s_idx]));
- break;
- }
- } /* while (s_idx < s_num_ranges) */
- } /* for (r_idx = 0; r_idx < r_num_ranges; r_idx++) */
-
- return result;
-}
-
-
diff --git a/tools/apriori/rangesort.h b/tools/apriori/rangesort.h
deleted file mode 100644
index 21db357..0000000
--- a/tools/apriori/rangesort.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef RANGESORT_H
-#define RANGESORT_H
-
-/* This implements a simple sorted list of non-overlapping ranges. */
-
-#include <debug.h>
-#include <common.h>
-#include <gelf.h>
-
-typedef enum range_error_t {
- ERROR_CONTAINS,
- ERROR_OVERLAPS
-} range_error_t;
-
-typedef struct range_t range_t;
-struct range_t {
- GElf_Off start;
- GElf_Off length;
- void *user;
- void (*err_fn)(range_error_t, range_t *, range_t *);
- void (*user_dtor)(void *);
-};
-
-typedef struct range_list_t range_list_t;
-
-range_list_t* init_range_list();
-void destroy_range_list(range_list_t *);
-
-/* Just adds a range to the list. We won't detect whether the range overlaps
- other ranges or contains them, or is contained by them, till we call
- sort_ranges(). */
-void add_unique_range_nosort(range_list_t *ranges,
- GElf_Off start, GElf_Off length,
- void *user,
- void (*err_fn)(range_error_t, range_t *, range_t *),
- void (*user_dtor)(void * ));
-
-/* Sorts the ranges. If there are overlapping ranges or ranges that contain
- other ranges, it will cause the program to exit with a FAIL. */
-range_list_t* sort_ranges(range_list_t *ranges);
-/* Find which range value falls in. Return that range or NULL if value does
- not fall within any range. */
-range_t *find_range(range_list_t *ranges, GElf_Off value);
-int get_num_ranges(const range_list_t *ranges);
-range_t *get_sorted_ranges(const range_list_t *ranges, int *num_ranges);
-GElf_Off get_last_address(const range_list_t *ranges);
-
-/* This returns a range_list_t handle that contains ranges composed of the
- adjacent ranges of the input range list. The user data of each range in
- the range list is a structure of the type contiguous_range_info_t.
- This structure contains an array of pointers to copies of the original
- range_t structures comprising each new contiguous range, as well as the
- length of that array.
-
- NOTE: The input range must be sorted!
-
- NOTE: destroy_range_list() will take care of releasing the data that it
- allocates as a result of calling get_contiguous_ranges(). Do not free that
- data yourself.
-
- NOTE: the user data of the original range_t structures is simply copied, so
- be careful handling it. You can destroy the range_list_t with
- destroy_range_list() as usual. On error, the function does not return--the
- program terminates.
-
- NOTE: The returned range is not sorted. You must call sort_ranges() if you
- need to.
-*/
-
-typedef struct {
- int num_ranges;
- range_t *ranges;
-} contiguous_range_info_t;
-
-range_list_t* get_contiguous_ranges(const range_list_t *);
-
-/* The function below takes in two range lists: r and s, and subtracts the
- ranges in s from those in r. For example, if r and s are as follows:
-
- r = { [0, 10) }
- s = { [3, 5), [7, 9) }
-
- Then r - s is { [0, 3), [5, 7), [9, 10) }
-
- NOTE: Both range lists must be sorted on input. This is guarded by an
- assertion.
-
- NOTE: Range s must contain ranges, which are fully contained by the span of
- range r (the span being the interval between the start of the lowest
- range in r, inclusive, and the end of the highest range in r,
- exclusive).
-
- NOTE: In addition to the requirement above, range s must contain ranges,
- each of which is a subrange of one of the ranges of r.
-
- NOTE: There is no user info associated with the resulting range.
-
- NOTE: The resulting range is not sorted.
-
- Ther returned list must be destroyed with destroy_range_list().
-*/
-
-range_list_t* subtract_ranges(const range_list_t *r, const range_list_t *s);
-
-#endif/*RANGESORT_H*/
diff --git a/tools/apriori/source.c b/tools/apriori/source.c
deleted file mode 100644
index 69c57c7..0000000
--- a/tools/apriori/source.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <source.h>
-
-void find_section(source_t *source, Elf64_Addr address,
- Elf_Scn **scn,
- GElf_Shdr *shdr,
- Elf_Data **data)
-{
- range_t *range = find_range(source->sorted_sections, address);
- FAILIF(NULL == range,
- "Cannot match address %lld to any range in [%s]!\n",
- address,
- source->name);
- *scn = (Elf_Scn *)range->user;
- ASSERT(*scn);
- FAILIF_LIBELF(NULL == gelf_getshdr(*scn, shdr), gelf_getshdr);
- *data = elf_getdata(*scn, NULL);
- FAILIF_LIBELF(NULL == *data, elf_getdata);
-}
diff --git a/tools/apriori/source.h b/tools/apriori/source.h
deleted file mode 100644
index 5381a29..0000000
--- a/tools/apriori/source.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef SOURCE_H
-#define SOURCE_H
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <libelf.h>
-#include <libebl.h>
-#ifdef ARM_SPECIFIC_HACKS
- #include <libebl_arm.h>
-#endif/*ARM_SPECIFIC_HACKS*/
-#include <elf.h>
-#include <gelf.h>
-#include <rangesort.h>
-#include <elfcopy.h>
-
-typedef struct source_t source_t;
-
-typedef struct {
- Elf_Scn *scn;
- GElf_Shdr shdr;
- Elf_Data *data;
- shdr_info_t *info;
-} section_info_t;
-
-typedef struct {
- GElf_Rel *rels;
- int num_rels; /* number of relocations that were not finished */
- int rels_size; /* this is the size of rels[], NOT the number of rels! */
-} unfinished_relocation_t;
-
-typedef struct {
- int processed;
- size_t idx; /* index of DT entry in the .dynamic section, if entry has a ptr value */
- Elf64_Addr addr; /* if DT entry's value is an address, we save it here */
- size_t sz_idx; /* index of DT entry in the .dynamic section, if entry has a size value */
- Elf64_Xword size; /* if DT entry's value is a size, we save it here */
-
- range_list_t *sections; /* list of sections corresponding to this entry */
- int num_unfinished_relocs; /* this variables is populated by adjust_dynamic_segment_for()
- during the second pass of the prelinker */
-} dt_rel_info_t;
-
-struct source_t {
- source_t *next;
-
- char *name; /* full path name of this executable file */
- char *output; /* name of the output file or directory */
- int output_is_dir; /* nonzero if output is a directory, 0 if output is a file */
- /* ELF-related information: */
- Elf *oldelf;
- Elf *elf;
- /* info[] is an array of structures describing the sections of the new ELF
- file. We populate the info[] array in clone_elf(), and use it to
- adjust the size of the ELF file when we modify the relocation-entry
- section.
- */
- shdr_info_t *shdr_info;
- GElf_Ehdr old_ehdr_mem; /* store ELF header of original library */
- GElf_Ehdr ehdr_mem; /* store ELF header of new library */
- GElf_Phdr *phdr_info;
- Ebl *ebl;
- Elf_Data *shstrtab_data;
- int elf_fd;
- int newelf_fd; /* fd of output file, -1 if output == NULL */
- int newelf_relo_fd; /* fd of relocaion output file */
- struct stat elf_file_info;
- GElf_Ehdr elf_hdr, oldelf_hdr;
- size_t shstrndx;
- int shnum; /* number of sections */
- int dry_run; /* 0 if we do not update the files, 1 (default) otherwise */
-
- section_info_t symtab;
- section_info_t strtab;
- section_info_t dynamic;
- section_info_t hash;
- section_info_t bss;
-
- range_list_t *sorted_sections;
-
- section_info_t *relocation_sections; /* relocation sections in file */
- int num_relocation_sections; /* number of relocation sections (<= relocation_sections_size) */
- int relocation_sections_size; /* sice of array -- NOT number of relocs! */
-
- /* relocation sections that contain relocations that could not be handled.
- This array is parallel to relocation_sections, and for each entry
- in that array, it contains a list of relocations that could not be
- handled.
- */
- unfinished_relocation_t *unfinished;
-
- /* The sections field of these two structuer contains a list of elements
- of the member variable relocations. */
- dt_rel_info_t rel;
- dt_rel_info_t jmprel;
-
- int num_syms; /* number of symbols in symbol table. This is the length of
- both exports[] and satisfied[] arrays. */
-
- /* This is an array that contains one element for each library dependency
- listed in the executable or shared library. */
- source_t **lib_deps; /* list of library dependencies */
- int num_lib_deps; /* actual number of library dependencies */
- int lib_deps_size; /* size of lib_deps array--NOT actual number of deps! */
-
- /* This is zero for executables. For shared libraries, it is the address
- at which the library was prelinked. */
- unsigned base;
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- /* When we read in a file, if it has the prelinked tag, we set prelinked
- to 1 and the prelink address in the tag to prelink_base. This address
- must match the value of base that we choose. */
- int prelinked;
- long prelink_base; /* valid if prelinked != 0 */
-#endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
-};
-
-extern void find_section(source_t *source, Elf64_Addr address,
- Elf_Scn **scn,
- GElf_Shdr *shdr,
- Elf_Data **data);
-
-#endif/*SOURCE_H*/
diff --git a/tools/apriori/tweak.h b/tools/apriori/tweak.h
deleted file mode 100755
index 3afedee..0000000
--- a/tools/apriori/tweak.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef TWEAK_H
-#define TWEAK_H
-
-#include <source.h>
-
-/* This function will break up the .bss section into multiple subsegments,
- depending on whether the .bss segment contains copy-relocated symbols. This
- will produce a nonstandard ELF file (with multiple .bss sections), tht the
- linker will need to know how to handle. The return value is the number of
- segments that the .bss segment was broken into (zero if the .bss segment was
- not modified. */
-
-int tweak_bss_if_necessary(source_t *source);
-
-#endif/*TWEAK_H*/
diff --git a/tools/iself/Android.mk b/tools/iself/Android.mk
deleted file mode 100755
index 49fabff..0000000
--- a/tools/iself/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for iself
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DDEBUG
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/
-
-LOCAL_SRC_FILES := \
- iself.c
-
-LOCAL_MODULE := iself
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/iself/debug.h b/tools/iself/debug.h
deleted file mode 100644
index 9bbf47f..0000000
--- a/tools/iself/debug.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#ifdef DEBUG
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
- #define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
- #define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size) {
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size) {
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr) {
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr) {
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR PRINT
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/tools/iself/iself.c b/tools/iself/iself.c
deleted file mode 100644
index e634a22..0000000
--- a/tools/iself/iself.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <debug.h>
-#include <unistd.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-
-int
-main(int argc, char **argv)
-{
- char *fname;
- int fd;
- char magic[4];
-
- argc--, argv++;
- FAILIF(argc != 1, "Expecting a file name!\n");
- fname = *argv;
-
- fd = open(fname, O_RDONLY);
- FAILIF(fd < 0, "Error opening %s for reading: %s (%d)!\n",
- fname, strerror(errno), errno);
-
- FAILIF(4 != read(fd, magic, 4),
- "Could not read first 4 bytes from %s: %s (%d)!\n",
- fname, strerror(errno), errno);
-
- if (magic[0] != 0x7f) return 1;
- if (magic[1] != 'E') return 1;
- if (magic[2] != 'L') return 1;
- if (magic[3] != 'F') return 1;
-
- return 0;
-}
diff --git a/tools/isprelinked/Android.mk b/tools/isprelinked/Android.mk
deleted file mode 100755
index e085f29..0000000
--- a/tools/isprelinked/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for apriori
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(TARGET_ARCH),arm)
-include $(CLEAR_VARS)
-
-LOCAL_LDLIBS += -ldl
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS
-LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
-LOCAL_CFLAGS += -DDEBUG
-
-ifeq ($(HOST_OS),windows)
-LOCAL_LDLIBS += -lintl
-endif
-
-LOCAL_SRC_FILES := \
- isprelinked.c \
- debug.c \
- prelink_info.c
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/ \
- external/elfutils/lib/ \
- external/elfutils/libelf/ \
- external/elfutils/libebl/ \
- external/elfcopy/
-
-LOCAL_STATIC_LIBRARIES := libelfcopy libelf libebl libebl_arm #dl
-
-LOCAL_MODULE := isprelinked
-
-include $(BUILD_HOST_EXECUTABLE)
-endif #TARGET_ARCH==arm
diff --git a/tools/isprelinked/common.h b/tools/isprelinked/common.h
deleted file mode 100644
index f5d9d2e..0000000
--- a/tools/isprelinked/common.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <libelf.h>
-#include <elf.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
-
-static inline int is_host_little(void)
-{
- short val = 0x10;
- return ((char *)&val)[0] != 0;
-}
-
-static inline long switch_endianness(long val)
-{
- long newval;
- ((char *)&newval)[3] = ((char *)&val)[0];
- ((char *)&newval)[2] = ((char *)&val)[1];
- ((char *)&newval)[1] = ((char *)&val)[2];
- ((char *)&newval)[0] = ((char *)&val)[3];
- return newval;
-}
-
-#endif/*COMMON_H*/
diff --git a/tools/isprelinked/debug.c b/tools/isprelinked/debug.c
deleted file mode 100644
index 6066543..0000000
--- a/tools/isprelinked/debug.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <debug.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#define NUM_COLS (32)
-
-int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) {
- int num_nonprintable = 0;
- int i, last;
- char *pchr = (char *)b;
- fputc('\n', s);
- for (i = last = 0; i < len; i++) {
- if (!elsize) {
- if (i && !(i % 4)) fprintf(s, " ");
- if (i && !(i % 8)) fprintf(s, " ");
- } else {
- if (i && !(i % elsize)) fprintf(s, " ");
- }
-
- if (i && !(i % NUM_COLS)) {
- while (last < i) {
- if (isprint(pchr[last]))
- fputc(pchr[last], s);
- else {
- fputc('.', s);
- num_nonprintable++;
- }
- last++;
- }
- fprintf(s, " (%d)\n", i);
- }
- fprintf(s, "%02x", (unsigned char)pchr[i]);
- }
- if (i && (i % NUM_COLS)) fputs("\n", s);
- return num_nonprintable;
-}
-
diff --git a/tools/isprelinked/debug.h b/tools/isprelinked/debug.h
deleted file mode 100644
index 3996898..0000000
--- a/tools/isprelinked/debug.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common.h>
-
-#ifdef DEBUG
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
- #define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
- #define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size) {
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size) {
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr) {
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr) {
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR PRINT
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/tools/isprelinked/isprelinked.c b/tools/isprelinked/isprelinked.c
deleted file mode 100644
index c677e39..0000000
--- a/tools/isprelinked/isprelinked.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* TODO:
- 1. check the ARM EABI version--this works for versions 1 and 2.
- 2. use a more-intelligent approach to finding the symbol table, symbol-string
- table, and the .dynamic section.
- 3. fix the determination of the host and ELF-file endianness
- 4. write the help screen
-*/
-
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <libebl.h>
-#ifdef ARM_SPECIFIC_HACKS
- #include <libebl_arm.h>
-#endif/*ARM_SPECIFIC_HACKS*/
-#include <elf.h>
-#include <gelf.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <rangesort.h>
-#include <prelink_info.h>
-#include <libgen.h>
-
-
-/* Flag set by --verbose. This variable is global as it is accessed by the
- macro INFO() in multiple compilation unites. */
-int verbose_flag = 0;
-/* Flag set by --quiet. This variable is global as it is accessed by the
- macro PRINT() in multiple compilation unites. */
-int quiet_flag = 0;
-
-int main(int argc, char **argv) {
-
- argc--, argv++;
- if (!argc)
- return 0;
-
- /* Check to see whether the ELF library is current. */
- FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n");
-
- const char *filename;
- for (; argc; argc--) {
- filename = *argv++;
-
- Elf *elf;
- GElf_Ehdr elf_hdr;
- int fd;
- int prelinked;
- long prelink_addr = 0;
-
- INFO("Processing file [%s]\n", filename);
-
- fd = open(filename, O_RDONLY);
- FAILIF(fd < 0, "open(%d): %s (%d).\n",
- filename,
- strerror(errno),
- errno);
-
- elf = elf_begin(fd, ELF_C_READ_MMAP_PRIVATE, NULL);
- FAILIF_LIBELF(elf == NULL, elf_begin);
-
- FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr),
- gelf_getehdr);
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- prelinked = check_prelinked(filename, elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
- &prelink_addr);
-#else
- #error 'SUPPORT_ANDROID_PRELINK_TAGS is not defined!'
-#endif
-
- if (prelinked)
- PRINT("%s: 0x%08x\n", filename, prelink_addr);
- else
- PRINT("%s: not prelinked\n", filename);
-
- FAILIF_LIBELF(elf_end(elf), elf_end);
- close(fd);
- }
-
- return 0;
-}
-
diff --git a/tools/isprelinked/prelink_info.c b/tools/isprelinked/prelink_info.c
deleted file mode 100644
index 21b1519..0000000
--- a/tools/isprelinked/prelink_info.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include <prelink_info.h>
-#include <debug.h>
-#include <common.h>
-
-typedef struct {
- long mmap_addr;
- char tag[4]; /* 'P', 'R', 'E', ' ' */
-} prelink_info_t __attribute__((packed));
-
-static inline void set_prelink(long *prelink_addr,
- int elf_little,
- prelink_info_t *info)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
- if (prelink_addr) {
- if (!(elf_little ^ is_host_little())) {
- /* Same endianness */
- *prelink_addr = info->mmap_addr;
- }
- else {
- /* Different endianness */
- *prelink_addr = switch_endianness(info->mmap_addr);
- }
- }
-}
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
- int fd = open(fname, O_RDONLY);
- FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
- fname, strerror(errno), errno);
- off_t end = lseek(fd, 0, SEEK_END);
-
- int nr = sizeof(prelink_info_t);
-
- off_t sz = lseek(fd, -nr, SEEK_CUR);
- ASSERT((long)(end - sz) == (long)nr);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- prelink_info_t info;
- int num_read = read(fd, &info, nr);
- FAILIF(num_read < 0,
- "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
- fd, strerror(errno), errno);
- FAILIF(num_read != sizeof(info),
- "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
- "expected (read %d)!\n",
- fd, sizeof(info), num_read);
-
- int prelinked = 0;
- if (!strncmp(info.tag, "PRE ", 4)) {
- set_prelink(prelink_addr, elf_little, &info);
- prelinked = 1;
- }
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
- return prelinked;
-}
-
-#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/
diff --git a/tools/isprelinked/prelink_info.h b/tools/isprelinked/prelink_info.h
deleted file mode 100644
index afc03e9..0000000
--- a/tools/isprelinked/prelink_info.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef PRELINK_INFO_H
-#define PRELINK_INFO_H
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr);
-
-#endif
-#endif/*PRELINK_INFO_H*/
diff --git a/tools/lsd/Android.mk b/tools/lsd/Android.mk
deleted file mode 100644
index a224741..0000000
--- a/tools/lsd/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for lsd
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(TARGET_ARCH),arm)
-include $(CLEAR_VARS)
-
-LOCAL_LDLIBS += -ldl
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DBIG_ENDIAN=1
-LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
-LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS
-LOCAL_CFLAGS += -DDEBUG
-
-ifeq ($(HOST_OS),windows)
-LOCAL_LDLIBS += -lintl
-endif
-
-LOCAL_SRC_FILES := \
- cmdline.c \
- debug.c \
- hash.c \
- lsd.c \
- main.c
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/ \
- external/elfutils/lib/ \
- external/elfutils/libelf/ \
- external/elfutils/libebl/
-
-LOCAL_STATIC_LIBRARIES := libelf libebl libebl_arm #dl
-
-LOCAL_MODULE := lsd
-
-include $(BUILD_HOST_EXECUTABLE)
-endif #TARGET_ARCH==arm
-
diff --git a/tools/lsd/cmdline.c b/tools/lsd/cmdline.c
deleted file mode 100644
index a3445cd..0000000
--- a/tools/lsd/cmdline.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <debug.h>
-#include <cmdline.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <ctype.h>
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-static struct option long_options[] = {
- {"verbose", no_argument, 0, 'V'},
- {"help", no_argument, 0, 'h'},
- {"print-info", no_argument, 0, 'p'},
- {"list-needed-libs", no_argument, 0, 'n'},
- {"lookup", required_argument, 0, 'L'},
- {0, 0, 0, 0},
-};
-
-/* This array must parallel long_options[] */
-static const char *descriptions[] = {
- "print verbose output",
- "print help screen",
- "for each file, generate a listing of all dependencies that each symbol "
- "satisfies",
- "print out a list of needed libraries",
- "provide a directory for library lookup"
-};
-
-void print_help(void)
-{
- fprintf(stdout,
- "invokation:\n"
- "\tlsd file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] "
- "[-Vpn]\n"
- "or\n"
- "\tlsd -h\n\n");
- fprintf(stdout, "options:\n");
- struct option *opt = long_options;
- const char **desc = descriptions;
- while (opt->name) {
- fprintf(stdout, "\t-%c\n"
- "\t--%-15s: %s\n",
- opt->val,
- opt->name,
- *desc);
- opt++;
- desc++;
- }
-}
-
-int get_options(int argc, char **argv,
- int *list_needed_libs,
- int *info,
- char ***dirs,
- int *num_dirs,
- int *verbose)
-{
- int c;
-
- ASSERT(list_needed_libs);
- *list_needed_libs = 0;
- ASSERT(info);
- *info = 0;
- ASSERT(verbose);
- *verbose = 0;
- ASSERT(dirs);
- *dirs = NULL;
- ASSERT(num_dirs);
- int size = 0;
- *num_dirs = 0;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long (argc, argv,
- "VhpnL:",
- long_options,
- &option_index);
- /* Detect the end of the options. */
- if (c == -1) break;
-
- if (isgraph(c)) {
- INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
- }
-
-#define SET_STRING_OPTION(name) do { \
- ASSERT(optarg); \
- (*name) = strdup(optarg); \
-} while(0)
-
- switch (c) {
- case 0:
- /* If this option set a flag, do nothing else now. */
- if (long_options[option_index].flag != 0)
- break;
- INFO ("option %s", long_options[option_index].name);
- if (optarg)
- INFO (" with arg %s", optarg);
- INFO ("\n");
- break;
- case 'h': print_help(); exit(1); break;
- case 'V': *verbose = 1; break;
- case 'p': *info = 1; break;
- case 'n': *list_needed_libs = 1; break;
- case 'L':
- {
- if (*num_dirs == size) {
- size += 10;
- *dirs = (char **)REALLOC(*dirs, size * sizeof(char *));
- }
- SET_STRING_OPTION(((*dirs) + *num_dirs));
- (*num_dirs)++;
- }
- break;
- case '?':
- /* getopt_long already printed an error message. */
- break;
-
-#undef SET_STRING_OPTION
-
- default:
- FAILIF(1, "Unknown option");
- }
- }
-
- return optind;
-}
diff --git a/tools/lsd/cmdline.h b/tools/lsd/cmdline.h
deleted file mode 100644
index fc3be3e..0000000
--- a/tools/lsd/cmdline.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef CMDLINE_H
-#define CMDLINE_H
-
-void print_help(void);
-
-int get_options(int argc, char **argv,
- int *list_needed_libs,
- int *info,
- char ***dirs,
- int *num_dirs,
- int *verbose);
-
-#endif/*CMDLINE_H*/
diff --git a/tools/lsd/common.h b/tools/lsd/common.h
deleted file mode 100644
index 6447b10..0000000
--- a/tools/lsd/common.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <libelf.h>
-#include <elf.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
-
-#endif/*COMMON_H*/
diff --git a/tools/lsd/debug.c b/tools/lsd/debug.c
deleted file mode 100644
index 54b18df..0000000
--- a/tools/lsd/debug.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <debug.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#define NUM_COLS (32)
-
-int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize)
-{
- int num_nonprintable = 0;
- int i, last;
- char *pchr = (char *)b;
- fputc('\n', s);
- for (i = last = 0; i < len; i++) {
- if (!elsize) {
- if (i && !(i % 4)) fprintf(s, " ");
- if (i && !(i % 8)) fprintf(s, " ");
- }
- else {
- if (i && !(i % elsize)) fprintf(s, " ");
- }
-
- if (i && !(i % NUM_COLS)) {
- while (last < i) {
- if (isprint(pchr[last]))
- fputc(pchr[last], s);
- else {
- fputc('.', s);
- num_nonprintable++;
- }
- last++;
- }
- fprintf(s, " (%d)\n", i);
- }
- fprintf(s, "%02x", (unsigned char)pchr[i]);
- }
- if (i && (i % NUM_COLS)) fputs("\n", s);
- return num_nonprintable;
-}
-
diff --git a/tools/lsd/debug.h b/tools/lsd/debug.h
deleted file mode 100644
index f7842f8..0000000
--- a/tools/lsd/debug.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common.h>
-
-#ifdef DEBUG
-
-#define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
-#define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
-#define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
-#define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size)
-{
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size)
-{
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size)
-{
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr)
-{
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr)
-{
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR(x...) fprintf(stderr, ##x)
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/tools/lsd/hash.c b/tools/lsd/hash.c
deleted file mode 100644
index bbac675..0000000
--- a/tools/lsd/hash.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <hash.h>
-#include <string.h>
-
-int hash_lookup(Elf *elf,
- Elf_Data *hash,
- Elf_Data *symtab,
- Elf_Data *symstr,
- const char *symname)
-{
- Elf32_Word *hash_data = (Elf32_Word *)hash->d_buf;
- Elf32_Word index;
- Elf32_Word nbuckets = *hash_data++;
- Elf32_Word *buckets = ++hash_data;
- Elf32_Word *chains = hash_data + nbuckets;
-
- index = buckets[elf_hash(symname) % nbuckets];
- while(index != STN_UNDEF &&
- strcmp((char *)symstr->d_buf +
- ((Elf32_Sym *)symtab->d_buf)[index].st_name,
- symname))
- {
- index = chains[index];
- }
-
- return index;
-}
diff --git a/tools/lsd/hash.h b/tools/lsd/hash.h
deleted file mode 100644
index af29b9e..0000000
--- a/tools/lsd/hash.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef HASH_H
-#define HASH_H
-
-#include <common.h>
-#include <libelf.h>
-#include <gelf.h>
-
-int hash_lookup(Elf *elf,
- Elf_Data *hash,
- Elf_Data *symtab,
- Elf_Data *symstr,
- const char *symname);
-
-#endif/*HASH_H*/
diff --git a/tools/lsd/lsd.c b/tools/lsd/lsd.c
deleted file mode 100644
index 03c235b..0000000
--- a/tools/lsd/lsd.c
+++ /dev/null
@@ -1,777 +0,0 @@
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <libebl.h>
-#include <elf.h>
-#include <gelf.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <hash.h>
-#include <lsd.h>
-
-extern int verbose_flag;
-
-typedef struct source_t source_t;
-
-typedef struct {
- Elf_Scn *scn;
- GElf_Shdr shdr;
- Elf_Data *data;
-} section_info_t;
-
-typedef struct next_export_t {
- source_t *source;
- int next_idx;
-} next_export_t;
-
-struct source_t {
- source_t *next;
- int visited;
-
- char *name; /* full path name of this executable file */
- /* ELF-related information: */
- Elf *elf;
- int elf_fd;
- GElf_Ehdr elf_hdr;
- size_t shstrndx;
- int shnum; /* number of sections */
-
- section_info_t symtab;
- section_info_t strtab;
- section_info_t dynamic;
- section_info_t hash;
-
- section_info_t *relocations;
- int num_relocations; /* number of relocs (<= relocations_size) */
- int relocations_size; /* sice of array -- NOT number of relocs! */
-
- /* satisfied_execs: array containing pointers to the libraries or
- executables that this executable satisfies symbol references for. */
- source_t **satisfied_execs;
- int num_satisfied_execs;
- int satisfied_execs_size;
-
- /* satisfied: array is parallel to symbol table; for each undefined symbol
- in that array, we maintain a flag stating whether that symbol has been
- satisfied, and if so, by which library. This applies both to executable
- files and libraries.
- */
- source_t **satisfied;
-
- /* exports: array is parallel to symbol table; for each global symbol
- in that array, we maintain a flag stating whether that symbol satisfies
- a dependency in some other file. num_syms is the length of the exports
- array, as well as the satisfied array. This applied to libraries only.
-
- next_exports: this is a bit tricky. We use this field to maintain a
- linked list of source_t for each global symbol of a shared library.
- For a shared library's global symbol at index N has the property that
- exports[N] is the head of a linked list (threaded through next_export)
- of all source_t that this symbol resolves a reference to. For example,
- if symbol printf has index 1000 in libc.so, and an executable A and
- library L use printf, then the source_t entry corresponding to libc.so
- will have exports[1000] be a linked list that contains the nodes for
- application A and library L.
- */
-
- next_export_t *exports;
- /* num_exported is the number of symbols in this file actually used by
- somebody else; it's not the size of the exports array. */
- int num_exported;
- next_export_t *next_export;
- int num_next_export;
- int next_export_size;
-
- int num_syms; /* number of symbols in symbol table. This is the length of
- both exports[] and satisfied[] arrays. */
-
- /* This is an array that contains one element for each library dependency
- listed in the executable or shared library. */
- source_t **lib_deps; /* list of library dependencies */
- int num_lib_deps; /* actual number of library dependencies */
- int lib_deps_size; /* size of lib_deps array--NOT actual number of deps! */
-
-};
-
-static source_t *sources = NULL;
-
-static char * find_file(const char *libname,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs);
-
-static inline source_t* find_source(const char *name,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs) {
- source_t *trav = sources;
- char *full = find_file(name, lib_lookup_dirs, num_lib_lookup_dirs);
- FAILIF(full == NULL, "Cannot construct full path for file [%s]!\n", name);
- while (trav) {
- if (!strcmp(trav->name, full))
- break;
- trav = trav->next;
- }
- free(full);
- return trav;
-}
-
-static inline void add_to_sources(source_t *src) {
- src->next = sources;
- sources = src;
-}
-
-static source_t* init_source(char *full_path) {
- source_t *source = (source_t *)CALLOC(1, sizeof(source_t));
-
- ASSERT(full_path);
- source->name = full_path;
- source->elf_fd = -1;
-
- INFO("Opening %s...\n", full_path);
- source->elf_fd = open(full_path, O_RDONLY);
- FAILIF(source->elf_fd < 0, "open(%s): %s (%d)\n",
- full_path,
- strerror(errno),
- errno);
- INFO("Calling elf_begin(%s)...\n", full_path);
- source->elf = elf_begin(source->elf_fd, ELF_C_READ, NULL);
- FAILIF_LIBELF(source->elf == NULL, elf_begin);
-
- /* libelf can recognize COFF and A.OUT formats, but we handle only ELF. */
- if (elf_kind(source->elf) != ELF_K_ELF) {
- ERROR("Input file %s is not in ELF format!\n", full_path);
- return NULL;
- }
-
- /* Make sure this is a shared library or an executable. */
- {
- INFO("Making sure %s is a shared library or an executable...\n",
- full_path);
- FAILIF_LIBELF(0 == gelf_getehdr(source->elf, &source->elf_hdr), gelf_getehdr);
- FAILIF(source->elf_hdr.e_type != ET_DYN &&
- source->elf_hdr.e_type != ET_EXEC,
- "%s must be a shared library (elf type is %d, expecting %d).\n",
- full_path,
- source->elf_hdr.e_type,
- ET_DYN);
- }
-
- /* Get the index of the section-header-strings-table section. */
- FAILIF_LIBELF(elf_getshstrndx (source->elf, &source->shstrndx) < 0,
- elf_getshstrndx);
-
- FAILIF_LIBELF(elf_getshnum (source->elf, &source->shnum) < 0, elf_getshnum);
-
- /* Find various sections. */
- size_t scnidx;
- Elf_Scn *scn;
- GElf_Shdr *shdr, shdr_mem;
- INFO("Locating %d sections in %s...\n", source->shnum, full_path);
- for (scnidx = 1; scnidx < source->shnum; scnidx++) {
- scn = elf_getscn(source->elf, scnidx);
- FAILIF_LIBELF(NULL == scn, elf_getscn);
- shdr = gelf_getshdr(scn, &shdr_mem);
- FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
- INFO("\tfound section [%s]...\n", elf_strptr(source->elf, source->shstrndx, shdr->sh_name));
- if (shdr->sh_type == SHT_DYNSYM) {
- source->symtab.scn = scn;
- source->symtab.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->symtab.data, elf_getdata);
- memcpy(&source->symtab.shdr, shdr, sizeof(GElf_Shdr));
-
- /* The sh_link field of the section header of the symbol table
- contains the index of the associated strings table. */
- source->strtab.scn = elf_getscn(source->elf,
- source->symtab.shdr.sh_link);
- FAILIF_LIBELF(NULL == source->strtab.scn, elf_getscn);
- FAILIF_LIBELF(NULL == gelf_getshdr(scn, &source->strtab.shdr),
- gelf_getshdr);
- source->strtab.data = elf_getdata(source->strtab.scn, NULL);
- FAILIF_LIBELF(NULL == source->strtab.data, elf_getdata);
- }
- else if (shdr->sh_type == SHT_DYNAMIC) {
- source->dynamic.scn = scn;
- source->dynamic.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->symtab.data, elf_getdata);
- memcpy(&source->dynamic.shdr, shdr, sizeof(GElf_Shdr));
- }
- else if (shdr->sh_type == SHT_HASH) {
- source->hash.scn = scn;
- source->hash.data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == source->hash.data, elf_getdata);
- memcpy(&source->hash.shdr, shdr, sizeof(GElf_Shdr));
- }
- else if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
- if (source->num_relocations == source->relocations_size) {
- source->relocations_size += 5;
- source->relocations =
- (section_info_t *)REALLOC(source->relocations,
- source->relocations_size *
- sizeof(section_info_t));
- }
- section_info_t *reloc =
- source->relocations + source->num_relocations;
- reloc->scn = scn;
- reloc->data = elf_getdata(scn, NULL);
- FAILIF_LIBELF(NULL == reloc->data, elf_getdata);
- memcpy(&reloc->shdr, shdr, sizeof(GElf_Shdr));
- source->num_relocations++;
- }
- }
-
- if (source->dynamic.scn == NULL) {
- INFO("File [%s] does not have a dynamic section!\n", full_path);
- return 0;
- }
-
- FAILIF(source->symtab.scn == NULL,
- "File [%s] does not have a dynamic symbol table!\n",
- full_path);
-
- FAILIF(source->hash.scn == NULL,
- "File [%s] does not have a hash table!\n",
- full_path);
- FAILIF(source->hash.shdr.sh_link != elf_ndxscn(source->symtab.scn),
- "Hash points to section %d, not to %d as expected!\n",
- source->hash.shdr.sh_link,
- elf_ndxscn(scn));
-
- /* Now, find out how many symbols we have and allocate the array of
- satisfied symbols.
-
- NOTE: We don't count the number of undefined symbols here; we will
- iterate over the symbol table later, and count them then, when it is
- more convenient.
- */
- size_t symsize = gelf_fsize (source->elf,
- ELF_T_SYM,
- 1, source->elf_hdr.e_version);
- ASSERT(symsize);
-
- source->num_syms = source->symtab.data->d_size / symsize;
- source->satisfied = (source_t **)CALLOC(source->num_syms,
- sizeof(source_t *));
- source->exports = (source_t **)CALLOC(source->num_syms,
- sizeof(next_export_t));
-
- source->num_exported = 0;
- source->satisfied_execs = NULL;
- source->num_satisfied_execs = 0;
- source->satisfied_execs_size = 0;
-
- add_to_sources(source);
- return source;
-}
-
-static void destroy_source(source_t *source) {
- FREE(source->satisfied_execs);
- FREE(source->satisfied);
- FREE(source->exports);
- FREE(source->next_export);
- FREE(source->lib_deps); /* list of library dependencies */
- FAILIF_LIBELF(elf_end(source->elf), elf_end);
- FAILIF(close(source->elf_fd) < 0, "Could not close file %s: %s (%d)!\n",
- source->name, strerror(errno), errno);
- FREE(source->name);
- FREE(source);
-}
-
-static void print_needed_libs(source_t *source)
-{
- size_t idx;
- for (idx = 0; idx < source->num_lib_deps; idx++) {
- PRINT("%s:%s\n",
- source->name,
- source->lib_deps[idx]->name);
- }
-}
-
-static int is_symbol_imported(source_t *source,
- GElf_Sym *sym,
- size_t symidx)
-{
- const char *symname = elf_strptr(source->elf,
- elf_ndxscn(source->strtab.scn),
- sym->st_name);
-
- /* A symbol is imported by an executable or a library if it is undefined
- and is either global or weak. There is an additional case for
- executables that we will check below. */
- if (sym->st_shndx == SHN_UNDEF &&
- (GELF_ST_BIND(sym->st_info) == STB_GLOBAL ||
- GELF_ST_BIND(sym->st_info) == STB_WEAK)) {
- INFO("*** symbol [%s:%s] is imported (UNDEFIEND).\n",
- source->name,
- symname);
- return 1;
- }
-
-#ifdef ARM_SPECIFIC_HACKS
- /* A symbol is imported by an executable if is marked as an undefined
- symbol--this is standard to all ELF formats. Alternatively, according
- to the ARM specifications, a symbol in a BSS section that is also marked
- by an R_ARM_COPY relocation is also imported. */
-
- if (source->elf_hdr.e_type != ET_EXEC) {
- INFO("is_symbol_imported(): [%s] is a library, "
- "no further checks.\n", source->name);
- return 0;
- }
-
- /* Is the symbol in the BSS section, and is there a COPY relocation on
- that symbol? */
- INFO("*** [%s:%s] checking further to see if symbol is imported.\n",
- source->name, symname);
- if (sym->st_shndx < source->shnum) {
- /* Is it the .bss section? */
- Elf_Scn *scn = elf_getscn(source->elf, sym->st_shndx);
- FAILIF_LIBELF(NULL == scn, elf_getscn);
- GElf_Shdr *shdr, shdr_mem;
- shdr = gelf_getshdr(scn, &shdr_mem);
- FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
- if (!strcmp(".bss", elf_strptr(source->elf,
- source->shstrndx,
- shdr->sh_name)))
- {
- /* Is there an R_ARM_COPY relocation on this symbol? Iterate
- over the list of relocation sections and scan each section for
- an entry that matches the symbol. */
- size_t idx;
- for (idx = 0; idx < source->num_relocations; idx++) {
- section_info_t *reloc = source->relocations + idx;
- /* Does the relocation section refer to the symbol table in
- which this symbol resides, and does it relocate the .bss
- section? */
- if (reloc->shdr.sh_link == elf_ndxscn(source->symtab.scn) &&
- reloc->shdr.sh_info == sym->st_shndx)
- {
- /* Go over the relocations and see if any of them matches
- our symbol. */
- size_t nrels = reloc->shdr.sh_size / reloc->shdr.sh_entsize;
- size_t relidx, newidx;
- if (reloc->shdr.sh_type == SHT_REL) {
- for (newidx = relidx = 0; relidx < nrels; ++relidx) {
- GElf_Rel rel_mem;
- FAILIF_LIBELF(gelf_getrel (reloc->data,
- relidx,
- &rel_mem) == NULL,
- gelf_getrel);
- if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_COPY &&
- GELF_R_SYM (rel_mem.r_info) == symidx)
- {
- INFO("*** symbol [%s:%s] is imported "
- "(DEFINED, REL-COPY-RELOCATED).\n",
- source->name,
- symname);
- return 1;
- }
- } /* for each rel entry... */
- } else {
- for (newidx = relidx = 0; relidx < nrels; ++relidx) {
- GElf_Rela rel_mem;
- FAILIF_LIBELF(gelf_getrela (reloc->data,
- relidx,
- &rel_mem) == NULL,
- gelf_getrela);
- if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_COPY &&
- GELF_R_SYM (rel_mem.r_info) == symidx)
- {
- INFO("*** symbol [%s:%s] is imported "
- "(DEFINED, RELA-COPY-RELOCATED).\n",
- source->name,
- symname);
- return 1;
- }
- } /* for each rela entry... */
- } /* if rel else rela */
- }
- }
- }
- }
-#endif/*ARM_SPECIFIC_HACKS*/
-
- return 0;
-}
-
-static void resolve(source_t *source) {
- /* Iterate the symbol table. For each undefined symbol, scan the
- list of dependencies till we find a global symbol in one of them that
- satisfies the undefined reference. At this point, we update both the
- satisfied[] array of the sources entry, as well as the exports array of
- the dependency where we found the match.
- */
-
- GElf_Sym *sym, sym_mem;
- size_t symidx;
- for (symidx = 0; symidx < source->num_syms; symidx++) {
- sym = gelf_getsymshndx(source->symtab.data,
- NULL,
- symidx,
- &sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- if (is_symbol_imported(source, sym, symidx))
- {
- /* This is an undefined symbol. Go over the list of libraries
- and look it up. */
- size_t libidx;
- int found = 0;
- source_t *last_found = NULL;
- const char *symname = elf_strptr(source->elf,
- elf_ndxscn(source->strtab.scn),
- sym->st_name);
- for (libidx = 0; libidx < source->num_lib_deps; libidx++) {
- source_t *lib = source->lib_deps[libidx];
- int lib_symidx = hash_lookup(lib->elf,
- lib->hash.data,
- lib->symtab.data,
- lib->strtab.data,
- symname);
- if (STN_UNDEF != lib_symidx)
- {
- /* We found the symbol--now check to see if it is global
- or weak. If this is the case, then the symbol satisfies
- the dependency. */
- GElf_Sym *lib_sym, lib_sym_mem;
- lib_sym = gelf_getsymshndx(lib->symtab.data,
- NULL,
- lib_symidx,
- &lib_sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == lib_sym, gelf_getsymshndx);
-
- if(lib_sym->st_shndx != STN_UNDEF &&
- (GELF_ST_BIND(lib_sym->st_info) == STB_GLOBAL ||
- GELF_ST_BIND(lib_sym->st_info) == STB_WEAK))
- {
- /* We found the symbol! Update the satisfied array at this
- index location. */
- source->satisfied[symidx] = lib;
- /* Now, link this structure into the linked list
- corresponding to the found symbol in the library's
- global array. */
- if (source->num_next_export == source->next_export_size) {
- source->next_export_size += 30;
- source->next_export =
- (source_t **)REALLOC(source->next_export,
- source->next_export_size *
- sizeof(struct next_export_t));
- }
- source->next_export[source->num_next_export] = lib->exports[lib_symidx];
- lib->exports[lib_symidx].source = source;
- lib->exports[lib_symidx].next_idx = source->num_next_export;
-
- source->num_next_export++;
- lib->num_exported++;
-
- INFO("[%s:%s (index %d)] satisfied by [%s] (index %d)\n",
- source->name,
- symname,
- symidx,
- lib->name,
- lib_symidx);
- if (found) {
- if (found == 1) {
- found++;
- ERROR("ERROR: multiple definitions found for [%s:%s]!\n",
- source->name, symname);
- ERROR("\tthis definition [%s]\n", lib->name);
- }
- ERROR("\tprevious definition [%s]\n", last_found->name);
- }
-
- last_found = lib;
- if (!found) found = 1;
- }
- }
- }
- if(found == 0) {
- ERROR("ERROR: could not find match for %s:%s.\n",
- source->name,
- symname);
- }
- } /* if we found the symbol... */
- } /* for each symbol... */
-} /* resolve() */
-
-static void print_used_symbols(source_t *source) {
-
- int name_len = strlen(source->name);
- static const char ext[] = ".syms";
- char *filter = (char *)MALLOC(name_len + sizeof(ext));
- strcpy(filter, source->name);
- strcpy(filter + name_len, ext);
-
- FILE *fp = fopen(filter, "w+");
- FAILIF(NULL == fp,
- "Can't open %s: %s (%d)\n",
- filter,
- strerror(errno), errno);
-
- /* Is anybody using the symbols defined in source? */
-
- if (source->num_exported > 0) {
- INFO("[%s] exports %d symbols to %d libraries and executables.\n",
- source->name,
- source->num_exported,
- source->num_satisfied_execs);
- size_t symidx;
- for (symidx = 0; symidx < source->num_syms; symidx++) {
- if (source->exports[symidx].source != NULL) {
- GElf_Sym *sym, sym_mem;
- sym = gelf_getsymshndx(source->symtab.data,
- NULL,
- symidx,
- &sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- fprintf(fp, "%s\n", elf_strptr(source->elf,
- elf_ndxscn(source->strtab.scn),
- sym->st_name));
- }
- }
- }
- else if (source->num_satisfied_execs > 0) {
-
- /* Is the source listed as a depenency on anyone? If so, then the source exports no symbols
- to anyone, but someone lists it as a dependency, which is unnecessary, so we print a warning.
- */
-
- ERROR("WARNING: [%s] is listed as a dependency in: ", source->name);
- int i;
- for (i = 0; i < source->num_satisfied_execs; i++) {
- ERROR(" [%s],", source->satisfied_execs[i]->name);
- }
- ERROR(" but none of its symbols are used!.\n");
- }
-#if 0 /* This is not really an error--a library's symbols may not be used anyone as specified in the ELF file,
- but someone may still open a library via dlopen().
- */
- else {
- ERROR("WARNING: None of [%s]'s symbols are used by any library or executable!\n", source->name);
- }
-#endif
-
- fclose(fp);
- FREE(filter);
-}
-
-static void print_symbol_references(source_t *source) {
-
- int name_len = strlen(source->name);
- static const char ext[] = ".info";
- char *filter = (char *)MALLOC(name_len + sizeof(ext));
- strcpy(filter, source->name);
- strcpy(filter + name_len, ext);
-
- FILE *fp = fopen(filter, "w+");
- FAILIF(NULL == fp,
- "Can't open %s: %s (%d)\n",
- filter,
- strerror(errno), errno);
-
- if (source->num_exported > 0) {
- size_t symidx;
- for (symidx = 0; symidx < source->num_syms; symidx++) {
- if (source->exports[symidx].source != NULL) {
- const char *symname;
- GElf_Sym *sym, sym_mem;
- sym = gelf_getsymshndx(source->symtab.data,
- NULL,
- symidx,
- &sym_mem,
- NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- symname = elf_strptr(source->elf,
- elf_ndxscn(source->strtab.scn),
- sym->st_name);
- fprintf(fp, "%s\n", symname);
- next_export_t *export = &source->exports[symidx];
- while (export->source != NULL) {
- //fprintf(stderr, "%s:%s\n", symname, export->source->name);
- fprintf(fp, "\t%s\n", export->source->name);
- export = &export->source->next_export[export->next_idx];
- }
- }
- }
- }
-
- fclose(fp);
- FREE(filter);
-}
-
-static char * find_file(const char *libname,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs) {
- if (libname[0] == '/') {
- /* This is an absolute path name--just return it. */
- INFO("ABSOLUTE PATH: [%s].\n", libname);
- return strdup(libname);
- } else {
- /* First try the working directory. */
- int fd;
- if ((fd = open(libname, O_RDONLY)) > 0) {
- close(fd);
- INFO("FOUND IN CURRENT DIR: [%s].\n", libname);
- return strdup(libname);
- } else {
- /* Iterate over all library paths. For each path, append the file
- name and see if there is a file at that place. If that fails,
- bail out. */
-
- char *name;
- while (num_lib_lookup_dirs--) {
- size_t lib_len = strlen(*lib_lookup_dirs);
- /* one extra character for the slash, and another for the
- terminating NULL. */
- name = (char *)MALLOC(lib_len + strlen(libname) + 2);
- strcpy(name, *lib_lookup_dirs);
- name[lib_len] = '/';
- strcpy(name + lib_len + 1, libname);
- if ((fd = open(name, O_RDONLY)) > 0) {
- close(fd);
- INFO("FOUND: [%s] in [%s].\n", libname, name);
- return name;
- }
- INFO("NOT FOUND: [%s] in [%s].\n", libname, name);
- free(name);
- }
- }
- }
- return NULL;
-}
-
-static source_t* process_library(const char *libname,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs) {
- source_t *source = find_source(libname, lib_lookup_dirs, num_lib_lookup_dirs);
- if (NULL == source) {
- INFO("Processing [%s].\n", libname);
- char *full = find_file(libname, lib_lookup_dirs, num_lib_lookup_dirs);
- FAILIF(NULL == full,
- "Could not find [%s] in the current directory or in any of "
- "the search paths!\n", libname);
- source = init_source(full);
- if (source) {
- GElf_Dyn *dyn, dyn_mem;
- size_t dynidx;
- size_t numdyn =
- source->dynamic.shdr.sh_size /
- source->dynamic.shdr.sh_entsize;
-
- for (dynidx = 0; dynidx < numdyn; dynidx++) {
- dyn = gelf_getdyn (source->dynamic.data,
- dynidx,
- &dyn_mem);
- FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
- if (dyn->d_tag == DT_NEEDED) {
- /* Process the needed library recursively. */
- const char *dep_lib =
- elf_strptr (source->elf,
- source->dynamic.shdr.sh_link,
- dyn->d_un.d_val);
- INFO("[%s] depends on [%s].\n", libname, dep_lib);
- source_t *dep = process_library(dep_lib,
- lib_lookup_dirs,
- num_lib_lookup_dirs);
-
- /* Tell dep that source depends on it. */
- if (dep->num_satisfied_execs == dep->satisfied_execs_size) {
- dep->satisfied_execs_size += 10;
- dep->satisfied_execs =
- REALLOC(dep->satisfied_execs,
- dep->satisfied_execs_size *
- sizeof(source_t *));
- }
- dep->satisfied_execs[dep->num_satisfied_execs++] = source;
-
- /* Add the library to the dependency list. */
- if (source->num_lib_deps == source->lib_deps_size) {
- source->lib_deps_size += 10;
- source->lib_deps = REALLOC(source->lib_deps,
- source->lib_deps_size *
- sizeof(source_t *));
- }
- source->lib_deps[source->num_lib_deps++] = dep;
- }
- } /* for each dynamic entry... */
- }
- } else INFO("[%s] has been processed already.\n", libname);
-
- return source;
-}
-
-void lsd(char **execs, int num_execs,
- int list_needed_libs,
- int print_info,
- char **lib_lookup_dirs, int num_lib_lookup_dirs) {
-
- source_t *source; /* for general usage */
- int input_idx;
-
- for (input_idx = 0; input_idx < num_execs; input_idx++) {
- INFO("executable: [%s]\n", execs[input_idx]);
- /* Here process library is actually processing the top-level executable
- files. */
- process_library(execs[input_idx], lib_lookup_dirs, num_lib_lookup_dirs);
- /* if source is NULL, then the respective executable is static */
- /* Mark the source as an executable */
- } /* for each input executable... */
-
- if (list_needed_libs) {
- source = sources;
- while (source) {
- print_needed_libs(source);
- source = source->next;
- }
- }
-
- /* Now, for each entry in the sources array, iterate its symbol table. For
- each undefined symbol, scan the list of dependencies till we find a
- global symbol in one of them that satisfies the undefined reference.
- At this point, we update both the satisfied[] array of the sources entry,
- as well as the exports array of the dependency where we found the match.
- */
-
- source = sources;
- while (source) {
- resolve(source);
- source = source->next;
- }
-
- /* We are done! Since the end result of our calculations is a set of
- symbols for each library that other libraries or executables link
- against, we iterate over the set of libraries one last time, and for
- each symbol that is marked as satisfying some dependence, we emit
- a line with the symbol's name to a text file derived from the library's
- name by appending the suffix .syms to it. */
-
- source = sources;
- while (source) {
- /* If it's a library, print the results. */
- if (source->elf_hdr.e_type == ET_DYN) {
- print_used_symbols(source);
- if (print_info)
- print_symbol_references(source);
- }
- source = source->next;
- }
-
- /* Free the resources--you can't do it in the loop above because function
- print_symbol_references() accesses nodes other than the one being
- iterated over.
- */
- source = sources;
- while (source) {
- source_t *old = source;
- source = source->next;
- /* Destroy the evidence. */
- destroy_source(old);
- }
-}
-
diff --git a/tools/lsd/lsd.h b/tools/lsd/lsd.h
deleted file mode 100644
index 883c423..0000000
--- a/tools/lsd/lsd.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef LSD_H
-#define LSD_H
-
-void lsd(char **execs, int num_execs,
- int list_needed_libs,
- int print_info,
- char **lib_lookup_dirs,
- int num_lib_lookup_dirs);
-
-#endif
diff --git a/tools/lsd/main.c b/tools/lsd/main.c
deleted file mode 100644
index f29157a..0000000
--- a/tools/lsd/main.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* TODO:
- 1. check the ARM EABI version--this works for versions 1 and 2.
- 2. use a more-intelligent approach to finding the symbol table, symbol-string
- table, and the .dynamic section.
- 3. fix the determination of the host and ELF-file endianness
- 4. write the help screen
-*/
-
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <elf.h>
-#include <gelf.h>
-#include <cmdline.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <lsd.h>
-
-/* Flag set by --verbose. This variable is global as it is accessed by the
- macro INFO() in multiple compilation unites. */
-int verbose_flag = 0;
-/* Flag set by --quiet. This variable is global as it is accessed by the
- macro PRINT() in multiple compilation unites. */
-int quiet_flag = 0;
-
-int main(int argc, char **argv)
-{
- char **lookup_dirs = NULL;
- int num_lookup_dirs;
- int print_info;
- int list_needed_libs;
-
- /* Do not issue INFO() statements before you call get_options() to set
- the verbose flag as necessary.
- */
-
- int first = get_options(argc, argv,
- &list_needed_libs,
- &print_info,
- &lookup_dirs,
- &num_lookup_dirs,
- &verbose_flag);
-
- if (first == argc) {
- print_help();
- FAILIF(1, "You must specify at least one input ELF file!\n");
- }
-
- /* Check to see whether the ELF library is current. */
- FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n");
-
- /* List symbol dependencies... */
- lsd(&argv[first], argc - first,
- list_needed_libs, print_info,
- lookup_dirs, num_lookup_dirs);
-
- FREE(lookup_dirs);
-
- return 0;
-}
-
diff --git a/tools/soslim/Android.mk b/tools/soslim/Android.mk
deleted file mode 100644
index 60a860a..0000000
--- a/tools/soslim/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for soslim
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(TARGET_ARCH),arm)
-include $(CLEAR_VARS)
-
-LOCAL_LDLIBS += -ldl
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DBIG_ENDIAN=1
-LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
-LOCAL_CFLAGS += -DSUPPORT_ANDROID_PRELINK_TAGS
-LOCAL_CFLAGS += -DDEBUG
-LOCAL_CFLAGS += -DSTRIP_STATIC_SYMBOLS
-LOCAL_CFLAGS += -DMOVE_SECTIONS_IN_RANGES
-
-ifeq ($(HOST_OS),windows)
-# Cygwin stat does not support ACCESSPERMS bitmask
-LOCAL_CFLAGS += -DACCESSPERMS=0777
-LOCAL_LDLIBS += -lintl
-endif
-
-LOCAL_SRC_FILES := \
- cmdline.c \
- common.c \
- debug.c \
- soslim.c \
- main.c \
- prelink_info.c \
- symfilter.c
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/ \
- external/elfutils/lib/ \
- external/elfutils/libelf/ \
- external/elfutils/libebl/ \
- external/elfcopy/
-
-LOCAL_STATIC_LIBRARIES := libelfcopy libelf libebl libebl_arm #dl
-
-LOCAL_MODULE := soslim
-
-include $(BUILD_HOST_EXECUTABLE)
-endif #TARGET_ARCH==arm
diff --git a/tools/soslim/cmdline.c b/tools/soslim/cmdline.c
deleted file mode 100644
index c2d5e71..0000000
--- a/tools/soslim/cmdline.c
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <debug.h>
-#include <cmdline.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <ctype.h>
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-static struct option long_options[] =
-{
- {"verbose", no_argument, 0, 'V'},
- {"quiet", no_argument, 0, 'Q'},
- {"shady", no_argument, 0, 'S'},
- {"print", no_argument, 0, 'p'},
- {"help", no_argument, 0, 'h'},
- {"outfile", required_argument, 0, 'o'},
- {"filter", required_argument, 0, 'f'},
- {"dry", no_argument, 0, 'n'},
- {"strip", no_argument, 0, 's'},
- {0, 0, 0, 0},
-};
-
-/* This array must parallel long_options[] */
-static
-const char *descriptions[sizeof(long_options)/sizeof(long_options[0])] = {
- "print verbose output",
- "suppress errors and warnings",
- "patch ABS symbols whose values coincide with section starts and ends",
- "print the symbol table (if specified, only -V is allowed)",
- "this help screen",
- "specify an output file (if not provided, input file is modified)",
- "specify a symbol-filter file",
- "dry run (perform all calculations but do not modify the ELF file)",
- "strip debug sections, if they are present"
-};
-
-void print_help(void)
-{
- fprintf(stdout,
- "invokation:\n"
- "\tsoslim file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] "
- "[-Vpn]\n"
- "or\n"
- "\tsoslim -h\n\n");
- fprintf(stdout, "options:\n");
- struct option *opt = long_options;
- const char **desc = descriptions;
- while (opt->name) {
- fprintf(stdout, "\t-%c/--%-15s %s\n",
- opt->val,
- opt->name,
- *desc);
- opt++;
- desc++;
- }
-}
-
-int get_options(int argc, char **argv,
- char **outfile,
- char **symsfile,
- int *print_symtab,
- int *verbose,
- int *quiet,
- int *shady,
- int *dry_run,
- int *strip_debug)
-{
- int c;
-
- ASSERT(outfile);
- *outfile = NULL;
- ASSERT(symsfile);
- *symsfile = NULL;
- ASSERT(print_symtab);
- *print_symtab = 0;
- ASSERT(verbose);
- *verbose = 0;
- ASSERT(quiet);
- *quiet = 0;
- ASSERT(shady);
- *shady = 0;
- ASSERT(dry_run);
- *dry_run = 0;
- ASSERT(strip_debug);
- *strip_debug = 0;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long (argc, argv,
- "QVSphi:o:y:Y:f:ns",
- long_options,
- &option_index);
- /* Detect the end of the options. */
- if (c == -1) break;
-
- if (isgraph(c)) {
- INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
- }
-
-#define SET_STRING_OPTION(name) do { \
- ASSERT(optarg); \
- *name = strdup(optarg); \
-} while(0)
-
- switch (c) {
- case 0:
- /* If this option set a flag, do nothing else now. */
- if (long_options[option_index].flag != 0)
- break;
- INFO ("option %s", long_options[option_index].name);
- if (optarg)
- INFO (" with arg %s", optarg);
- INFO ("\n");
- break;
- case 'p': *print_symtab = 1; break;
- case 'h': print_help(); exit(1); break;
- case 'V': *verbose = 1; break;
- case 'Q': *quiet = 1; break;
- case 'S': *shady = 1; break;
- case 'n': *dry_run = 1; break;
- case 's': *strip_debug = 1; break;
- case 'o': SET_STRING_OPTION(outfile); break;
- case 'f': SET_STRING_OPTION(symsfile); break;
- case '?':
- /* getopt_long already printed an error message. */
- break;
-
-#undef SET_STRING_OPTION
-
- default:
- FAILIF(1, "Unknown option");
- }
- }
-
- return optind;
-}
diff --git a/tools/soslim/cmdline.h b/tools/soslim/cmdline.h
deleted file mode 100644
index bfc431e..0000000
--- a/tools/soslim/cmdline.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef CMDLINE_H
-#define CMDLINE_H
-
-void print_help(void);
-
-int get_options(int argc, char **argv,
- char **outfile,
- char **symsfile,
- int *print_symtab,
- int *verbose,
- int *quiet,
- int *shady,
- int *dry_run,
- int *strip_debug);
-
-#endif/*CMDLINE_H*/
diff --git a/tools/soslim/common.c b/tools/soslim/common.c
deleted file mode 100644
index b90cf41..0000000
--- a/tools/soslim/common.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <stdlib.h>
-#include <common.h>
-#include <debug.h>
-
-void map_over_sections(Elf *elf,
- section_match_fn_t match,
- void *user_data)
-{
- Elf_Scn* section = NULL;
- while ((section = elf_nextscn(elf, section)) != NULL) {
- if (match(elf, section, user_data))
- return;
- }
-}
-
-void map_over_segments(Elf *elf,
- segment_match_fn_t match,
- void *user_data)
-{
- Elf32_Ehdr *ehdr;
- Elf32_Phdr *phdr;
- int index;
-
- ehdr = elf32_getehdr(elf);
- phdr = elf32_getphdr(elf);
-
- INFO("Scanning over %d program segments...\n",
- ehdr->e_phnum);
-
- for (index = ehdr->e_phnum; index; index--) {
- if (match(elf, phdr++, user_data))
- return;
- }
-}
-
diff --git a/tools/soslim/common.h b/tools/soslim/common.h
deleted file mode 100644
index dacf930..0000000
--- a/tools/soslim/common.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <libelf.h>
-#include <elf.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
-
-typedef int (*section_match_fn_t)(Elf *, Elf_Scn *, void *);
-void map_over_sections(Elf *, section_match_fn_t, void *);
-
-typedef int (*segment_match_fn_t)(Elf *, Elf32_Phdr *, void *);
-void map_over_segments(Elf *, segment_match_fn_t, void *);
-
-typedef struct {
- Elf_Scn *sect;
- Elf32_Shdr *hdr;
- Elf_Data *data;
- size_t index;
-} section_info_t;
-
-static inline void get_section_info(Elf_Scn *sect, section_info_t *info)
-{
- info->sect = sect;
- info->data = elf_getdata(sect, 0);
- info->hdr = elf32_getshdr(sect);
- info->index = elf_ndxscn(sect);
-}
-
-static inline int is_host_little(void)
-{
- short val = 0x10;
- return ((char *)&val)[0] != 0;
-}
-
-static inline long switch_endianness(long val)
-{
- long newval;
- ((char *)&newval)[3] = ((char *)&val)[0];
- ((char *)&newval)[2] = ((char *)&val)[1];
- ((char *)&newval)[1] = ((char *)&val)[2];
- ((char *)&newval)[0] = ((char *)&val)[3];
- return newval;
-}
-
-#endif/*COMMON_H*/
diff --git a/tools/soslim/debug.c b/tools/soslim/debug.c
deleted file mode 100644
index b8365af..0000000
--- a/tools/soslim/debug.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <debug.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#if 0
-
-#define NUM_COLS (32)
-
-int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) {
- int num_nonprintable = 0;
- int i, last;
- char *pchr = (char *)b;
- fputc('\n', s);
- for (i = last = 0; i < len; i++) {
- if (!elsize) {
- if (i && !(i % 4)) fprintf(s, " ");
- if (i && !(i % 8)) fprintf(s, " ");
- } else {
- if (i && !(i % elsize)) fprintf(s, " ");
- }
-
- if (i && !(i % NUM_COLS)) {
- while (last < i) {
- if (isprint(pchr[last]))
- fputc(pchr[last], s);
- else {
- fputc('.', s);
- num_nonprintable++;
- }
- last++;
- }
- fprintf(s, " (%d)\n", i);
- }
- fprintf(s, "%02x", (unsigned char)pchr[i]);
- }
- if (i && (i % NUM_COLS)) fputs("\n", s);
- return num_nonprintable;
-}
-
-#endif
diff --git a/tools/soslim/debug.h b/tools/soslim/debug.h
deleted file mode 100644
index e7a2f9a..0000000
--- a/tools/soslim/debug.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common.h>
-
-#ifdef DEBUG
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
- #define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
- #define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size) {
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size) {
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr) {
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr) {
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR(x...) fprintf(stderr, ##x)
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/tools/soslim/main.c b/tools/soslim/main.c
deleted file mode 100644
index df48484..0000000
--- a/tools/soslim/main.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* TODO:
- 1. check the ARM EABI version--this works for versions 1 and 2.
- 2. use a more-intelligent approach to finding the symbol table, symbol-string
- table, and the .dynamic section.
- 3. fix the determination of the host and ELF-file endianness
- 4. write the help screen
-*/
-
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <hash.h>
-#include <libelf.h>
-#include <elf.h>
-#include <gelf.h>
-#include <cmdline.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <soslim.h>
-#include <symfilter.h>
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-#include <prelink_info.h>
-#endif
-
-/* Flag set by --verbose. This variable is global as it is accessed by the
- macro INFO() in multiple compilation unites. */
-int verbose_flag = 0;
-/* Flag set by --quiet. This variable is global as it is accessed by the
- macro PRINT() in multiple compilation unites. */
-int quiet_flag = 0;
-static void print_dynamic_symbols(Elf *elf, const char *symtab_name);
-
-int main(int argc, char **argv)
-{
- int elf_fd = -1, newelf_fd = -1;
- Elf *elf = NULL, *newelf = NULL;
- char *infile = NULL;
- char *outfile = NULL;
- char *symsfile_name = NULL;
- int print_symtab = 0;
- int shady = 0;
- int dry_run = 0;
- int strip_debug = 0;
-
- /* Do not issue INFO() statements before you call get_options() to set
- the verbose flag as necessary.
- */
-
- int first = get_options(argc, argv,
- &outfile,
- &symsfile_name,
- &print_symtab,
- &verbose_flag,
- &quiet_flag,
- &shady,
- &dry_run,
- &strip_debug);
-
- if ((print_symtab && (first == argc)) ||
- (!print_symtab && first + 1 != argc)) {
- print_help();
- FAILIF(1, "You must specify an input ELF file!\n");
- }
- FAILIF(print_symtab && (outfile || symsfile_name || shady),
- "You cannot provide --print and --outfile, --filter options, or "
- "--shady simultaneously!\n");
- FAILIF(dry_run && outfile,
- "You cannot have a dry run and output a file at the same time.");
-
- /* Check to see whether the ELF library is current. */
- FAILIF (elf_version(EV_CURRENT) == EV_NONE, "libelf is out of date!\n");
-
- if (print_symtab) {
-
- while (first < argc) {
- infile = argv[first++];
-
- INFO("Opening %s...\n", infile);
- elf_fd = open(infile, O_RDONLY);
- FAILIF(elf_fd < 0, "open(%s): %s (%d)\n",
- infile,
- strerror(errno),
- errno);
- INFO("Calling elf_begin(%s)...\n", infile);
- elf = elf_begin(elf_fd, ELF_C_READ, NULL);
- FAILIF_LIBELF(elf == NULL, elf_begin);
-
- /* libelf can recognize COFF and A.OUT formats, but we handle only
- ELF. */
- FAILIF(elf_kind(elf) != ELF_K_ELF,
- "Input file %s is not in ELF format!\n",
- infile);
-
- /* Make sure this is a shared library or an executable. */
- {
- GElf_Ehdr elf_hdr;
- INFO("Making sure %s is a shared library or an executable.\n",
- infile);
- FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr), gelf_getehdr);
- FAILIF(elf_hdr.e_type != ET_DYN &&
- elf_hdr.e_type != ET_EXEC,
- "%s must be a shared library or an executable "
- "(elf type is %d).\n",
- infile,
- elf_hdr.e_type);
- }
-
- print_dynamic_symbols(elf, infile);
-
- FAILIF_LIBELF(elf_end(elf), elf_end);
- FAILIF(close(elf_fd) < 0, "Could not close file %s: %s (%d)!\n",
- infile, strerror(errno), errno);
- }
- }
- else {
- int elf_fd = -1;
- Elf *elf = NULL;
- infile = argv[first];
-
- INFO("Opening %s...\n", infile);
- elf_fd = open(infile, ((outfile == NULL && dry_run == 0) ? O_RDWR : O_RDONLY));
- FAILIF(elf_fd < 0, "open(%s): %s (%d)\n",
- infile,
- strerror(errno),
- errno);
- INFO("Calling elf_begin(%s)...\n", infile);
- elf = elf_begin(elf_fd,
- ((outfile == NULL && dry_run == 0) ? ELF_C_RDWR : ELF_C_READ),
- NULL);
- FAILIF_LIBELF(elf == NULL, elf_begin);
-
- /* libelf can recognize COFF and A.OUT formats, but we handle only ELF. */
- FAILIF(elf_kind(elf) != ELF_K_ELF,
- "Input file %s is not in ELF format!\n",
- infile);
-
- /* We run a better check in adjust_elf() itself. It is permissible to call adjust_elf()
- on an executable if we are only stripping sections from the executable, not rearranging
- or moving sections.
- */
- if (0) {
- /* Make sure this is a shared library. */
- GElf_Ehdr elf_hdr;
- INFO("Making sure %s is a shared library...\n", infile);
- FAILIF_LIBELF(0 == gelf_getehdr(elf, &elf_hdr), gelf_getehdr);
- FAILIF(elf_hdr.e_type != ET_DYN,
- "%s must be a shared library (elf type is %d, expecting %d).\n",
- infile,
- elf_hdr.e_type,
- ET_DYN);
- }
-
- if (outfile != NULL) {
- ASSERT(!dry_run);
- struct stat st;
- FAILIF(fstat (elf_fd, &st) != 0,
- "Cannot stat input file %s: %s (%d)!\n",
- infile, strerror(errno), errno);
- newelf_fd = open (outfile, O_RDWR | O_CREAT | O_TRUNC,
- st.st_mode & ACCESSPERMS);
- FAILIF(newelf_fd < 0, "Cannot create file %s: %s (%d)!\n",
- outfile, strerror(errno), errno);
- INFO("Output file is [%s].\n", outfile);
- newelf = elf_begin(newelf_fd, ELF_C_WRITE_MMAP, NULL);
- } else {
- INFO("Modifying [%s] in-place.\n", infile);
- newelf = elf_clone(elf, ELF_C_EMPTY);
- }
-
- symfilter_t symfilter;
-
- symfilter.symbols_to_keep = NULL;
- symfilter.num_symbols_to_keep = 0;
- if (symsfile_name) {
- /* Make sure that the file is not empty. */
- struct stat s;
- FAILIF(stat(symsfile_name, &s) < 0,
- "Cannot stat file %s.\n", symsfile_name);
- if (s.st_size) {
- INFO("Building symbol filter.\n");
- build_symfilter(symsfile_name, elf, &symfilter, s.st_size);
- }
- else INFO("Not building symbol filter, filter file is empty.\n");
- }
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- int prelinked = 0, retouched = 0;
- int elf_little; /* valid if prelinked != 0 */
- long prelink_addr; /* valid if prelinked != 0 */
-#define RETOUCH_MAX_SIZE 600000
- /* _cnt valid if retouched != 0 */
- unsigned int retouch_byte_cnt = RETOUCH_MAX_SIZE;
- char retouch_buf[RETOUCH_MAX_SIZE]; /* valid if retouched != 0 */
-#endif
- clone_elf(elf, newelf,
- infile, outfile,
- symfilter.symbols_to_keep,
- symfilter.num_symbols_to_keep,
- shady
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- , &prelinked,
- &elf_little,
- &prelink_addr,
- &retouched,
- &retouch_byte_cnt,
- retouch_buf
-#endif
- ,
- true, /* rebuild the section-header-strings table */
- strip_debug,
- dry_run);
-
- if (symsfile_name && symfilter.symbols_to_keep != NULL) {
- destroy_symfilter(&symfilter);
- }
-
- if (outfile != NULL) INFO("Closing %s...\n", outfile);
- FAILIF_LIBELF(elf_end (newelf) != 0, elf_end);
- FAILIF(newelf_fd >= 0 && close(newelf_fd) < 0,
- "Could not close file %s: %s (%d)!\n",
- outfile, strerror(errno), errno);
-
- INFO("Closing %s...\n", infile);
- FAILIF_LIBELF(elf_end(elf), elf_end);
- FAILIF(close(elf_fd) < 0, "Could not close file %s: %s (%d)!\n",
- infile, strerror(errno), errno);
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- if (retouched) {
- INFO("File has retouch data, putting it back in place.\n");
- retouch_dump(outfile != NULL ? outfile : infile,
- elf_little,
- retouch_byte_cnt,
- retouch_buf);
- }
- if (prelinked) {
- INFO("File is prelinked, putting prelink TAG back in place.\n");
- setup_prelink_info(outfile != NULL ? outfile : infile,
- elf_little,
- prelink_addr);
- }
-#endif
- }
-
- FREEIF(outfile);
- return 0;
-}
-
-static void print_dynamic_symbols(Elf *elf, const char *file)
-{
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr;
-
- GElf_Ehdr ehdr;
- FAILIF_LIBELF(0 == gelf_getehdr(elf, &ehdr), gelf_getehdr);
- while ((scn = elf_nextscn (elf, scn)) != NULL) {
- FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr), gelf_getshdr);
- if (SHT_DYNSYM == shdr.sh_type) {
- /* This failure is too restrictive. There is no reason why
- the symbol table couldn't be called something else, but
- there is a standard name, and chances are that if we don't
- see it, there's something wrong.
- */
- size_t shstrndx;
- FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0,
- elf_getshstrndx);
- /* Now print the symbols. */
- {
- Elf_Data *symdata;
- size_t elsize;
- symdata = elf_getdata (scn, NULL); /* get the symbol data */
- FAILIF_LIBELF(NULL == symdata, elf_getdata);
- /* Get the number of section. We need to compare agains this
- value for symbols that have special info in their section
- references */
- size_t shnum;
- FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
- /* Retrieve the size of a symbol entry */
- elsize = gelf_fsize(elf, ELF_T_SYM, 1, ehdr.e_version);
-
- size_t index;
- for (index = 0; index < symdata->d_size / elsize; index++) {
- GElf_Sym sym_mem;
- GElf_Sym *sym;
- /* Get the symbol. */
- sym = gelf_getsymshndx (symdata, NULL,
- index, &sym_mem, NULL);
- FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);
- /* Print the symbol. */
- char bind = '?';
- switch(ELF32_ST_BIND(sym->st_info))
- {
- case STB_LOCAL: bind = 'l'; break;
- case STB_GLOBAL: bind = 'g'; break;
- case STB_WEAK: bind = 'w'; break;
- default: break;
- }
- char type = '?';
- switch(ELF32_ST_TYPE(sym->st_info))
- {
- case STT_NOTYPE: /* Symbol type is unspecified */
- type = '?';
- break;
- case STT_OBJECT: /* Symbol is a data object */
- type = 'o';
- break;
- case STT_FUNC: /* Symbol is a code object */
- type = 'f';
- break;
- case STT_SECTION:/* Symbol associated with a section */
- type = 's';
- break;
- case STT_FILE: /* Symbol's name is file name */
- type = 'f';
- break;
- case STT_COMMON: /* Symbol is a common data object */
- type = 'c';
- break;
- case STT_TLS: /* Symbol is thread-local data object*/
- type = 't';
- break;
- }
- {
- int till_lineno;
- int lineno;
- const char *section_name = "(unknown)";
- FAILIF(sym->st_shndx == SHN_XINDEX,
- "Can't handle symbol's st_shndx == SHN_XINDEX!\n");
- if (sym->st_shndx != SHN_UNDEF &&
- sym->st_shndx < shnum) {
- Elf_Scn *symscn = elf_getscn(elf, sym->st_shndx);
- FAILIF_LIBELF(NULL == symscn, elf_getscn);
- GElf_Shdr symscn_shdr;
- FAILIF_LIBELF(NULL == gelf_getshdr(symscn,
- &symscn_shdr),
- gelf_getshdr);
- section_name = elf_strptr(elf, shstrndx,
- symscn_shdr.sh_name);
- }
- else if (sym->st_shndx == SHN_ABS) {
- section_name = "SHN_ABS";
- }
- else if (sym->st_shndx == SHN_COMMON) {
- section_name = "SHN_COMMON";
- }
- else if (sym->st_shndx == SHN_UNDEF) {
- section_name = "(undefined)";
- }
- /* value size binding type section symname */
- PRINT("%-15s %8zd: %08llx %08llx %c%c %5d %n%s%n",
- file,
- index,
- sym->st_value, sym->st_size, bind, type,
- sym->st_shndx,
- &till_lineno,
- section_name,
- &lineno);
- lineno -= till_lineno;
- /* Create padding for section names of 15 chars.
- This limit is somewhat arbitratry. */
- while (lineno++ < 15) PRINT(" ");
- PRINT("(%d) %s\n",
- sym->st_name,
- elf_strptr(elf, shdr.sh_link, sym->st_name));
- }
- }
- }
- } /* if (shdr.sh_type = SHT_DYNSYM) */
- } /* while ((scn = elf_nextscn (elf, scn)) != NULL) */
-}
diff --git a/tools/soslim/prelink_info.c b/tools/soslim/prelink_info.c
deleted file mode 100644
index 2600ac7..0000000
--- a/tools/soslim/prelink_info.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include <prelink_info.h>
-#include <debug.h>
-#include <common.h>
-
-#define RETOUCH_SUFFIX_SIZE 12
-typedef struct {
- uint32_t mmap_addr;
- char tag[4]; /* 'P', 'R', 'E', ' ' */
-} __attribute__((packed)) prelink_info_t;
-
-static inline void set_prelink(long *prelink_addr,
- int elf_little,
- prelink_info_t *info)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
- if (prelink_addr) {
- if (!(elf_little ^ is_host_little())) {
- /* Same endianness */
- *prelink_addr = info->mmap_addr;
- }
- else {
- /* Different endianness */
- *prelink_addr = switch_endianness(info->mmap_addr);
- }
- }
-}
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
- int fd = open(fname, O_RDONLY);
- FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
- fname, strerror(errno), errno);
- off_t end = lseek(fd, 0, SEEK_END);
-#ifndef DEBUG
- (void)end;
-#endif
-
- int nr = sizeof(prelink_info_t);
-
- off_t sz = lseek(fd, -nr, SEEK_CUR);
- ASSERT((long)(end - sz) == (long)nr);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- prelink_info_t info;
- ssize_t num_read = read(fd, &info, nr);
- FAILIF(num_read < 0,
- "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
- fd, strerror(errno), errno);
- FAILIF((size_t)num_read != sizeof(info),
- "read(%d, &info, sizeof(prelink_info_t)): did not read %zd bytes as "
- "expected (read %zd)!\n",
- fd, sizeof(info), (size_t)num_read);
-
- int prelinked = 0;
- if (!strncmp(info.tag, "PRE ", 4)) {
- set_prelink(prelink_addr, elf_little, &info);
- prelinked = 1;
- }
- FAILIF(close(fd) < 0,
- "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
- return prelinked;
-}
-
-int check_retouched(const char *fname, int elf_little,
- unsigned int *retouch_byte_cnt, char *retouch_buf) {
- FAILIF(sizeof(prelink_info_t) != 8,
- "Unexpected sizeof(prelink_info_t) == %d!\n",
- sizeof(prelink_info_t));
- int fd = open(fname, O_RDONLY);
- FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
- fname, strerror(errno), errno);
- off_t end = lseek(fd, 0, SEEK_END);
- int nr = sizeof(prelink_info_t);
- off_t sz = lseek(fd, -nr-RETOUCH_SUFFIX_SIZE, SEEK_CUR);
- ASSERT((long)(end - sz) == (long)(nr+RETOUCH_SUFFIX_SIZE));
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- char retouch_meta[RETOUCH_SUFFIX_SIZE];
- int num_read = read(fd, &retouch_meta, RETOUCH_SUFFIX_SIZE);
- FAILIF(num_read < 0,
- "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
- fd, strerror(errno), errno);
- FAILIF(num_read != RETOUCH_SUFFIX_SIZE,
- "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
- "expected (read %d)!\n",
- fd, RETOUCH_SUFFIX_SIZE, num_read);
-
- int retouched = 0;
- if (!strncmp(retouch_meta, "RETOUCH ", 8)) {
- unsigned int retouch_byte_cnt_meta;
- if (!(elf_little ^ is_host_little()))
- retouch_byte_cnt_meta = *(unsigned int *)(retouch_meta+8);
- else
- retouch_byte_cnt_meta =
- switch_endianness(*(unsigned int *)(retouch_meta+8));
- FAILIF(*retouch_byte_cnt < retouch_byte_cnt_meta,
- "Retouch buffer too small at %d bytes (%d needed).",
- *retouch_byte_cnt, retouch_byte_cnt_meta);
- *retouch_byte_cnt = retouch_byte_cnt_meta;
- off_t sz = lseek(fd,
- -((long)*retouch_byte_cnt)-RETOUCH_SUFFIX_SIZE-nr,
- SEEK_END);
- ASSERT((long)(end - sz) ==
- (long)(*retouch_byte_cnt+RETOUCH_SUFFIX_SIZE+nr));
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
- num_read = read(fd, retouch_buf, *retouch_byte_cnt);
- FAILIF(num_read < 0,
- "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
- fd, strerror(errno), errno);
- FAILIF(num_read != *retouch_byte_cnt,
- "read(%d, retouch_buf, %u): did not read %d bytes as "
- "expected (read %d)!\n",
- fd, *retouch_byte_cnt, *retouch_byte_cnt, num_read);
-
- retouched = 1;
- }
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
- return retouched;
-}
-
-void retouch_dump(const char *fname, int elf_little,
- unsigned int retouch_byte_cnt, char *retouch_buf) {
- int fd = open(fname, O_WRONLY);
- FAILIF(fd < 0,
- "open(%s, O_WRONLY): %s (%d)\n",
- fname, strerror(errno), errno);
- off_t sz = lseek(fd, 0, SEEK_END);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte
- // size of the retouch blob, in target endianness.
- strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8);
- if (elf_little ^ is_host_little()) {
- *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
- switch_endianness(retouch_byte_cnt);
- } else {
- *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
- retouch_byte_cnt;
- }
-
- int num_written = write(fd, retouch_buf, retouch_byte_cnt+12);
- FAILIF(num_written < 0,
- "write(%d, &info, sizeof(info)): %s (%d)\n",
- fd, strerror(errno), errno);
- FAILIF((retouch_byte_cnt+12) != num_written,
- "Could not write %d bytes as expected (wrote %d bytes instead)!\n",
- retouch_byte_cnt, num_written);
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
-}
-
-void setup_prelink_info(const char *fname, int elf_little, long base)
-{
- FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
- int fd = open(fname, O_WRONLY);
- FAILIF(fd < 0,
- "open(%s, O_WRONLY): %s (%d)\n" ,
- fname, strerror(errno), errno);
- prelink_info_t info;
- off_t sz = lseek(fd, 0, SEEK_END);
- FAILIF(sz == (off_t)-1,
- "lseek(%d, 0, SEEK_END): %s (%d)!\n",
- fd, strerror(errno), errno);
-
- if (!(elf_little ^ is_host_little())) {
- /* Same endianness */
- INFO("Host and ELF file [%s] have same endianness.\n", fname);
- info.mmap_addr = base;
- }
- else {
- /* Different endianness */
- INFO("Host and ELF file [%s] have different endianness.\n", fname);
- info.mmap_addr = switch_endianness(base);
- }
- strncpy(info.tag, "PRE ", 4);
-
- ssize_t num_written = write(fd, &info, sizeof(info));
- FAILIF(num_written < 0,
- "write(%d, &info, sizeof(info)): %s (%d)\n",
- fd, strerror(errno), errno);
- FAILIF(sizeof(info) != (size_t)num_written,
- "Could not write %zd bytes (wrote only %zd bytes) as expected!\n",
- sizeof(info), (size_t)num_written);
- FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
-}
-
-#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/
diff --git a/tools/soslim/prelink_info.h b/tools/soslim/prelink_info.h
deleted file mode 100644
index efa84fd..0000000
--- a/tools/soslim/prelink_info.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef PRELINK_INFO_H
-#define PRELINK_INFO_H
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-
-int check_prelinked(const char *fname, int elf_little, long *prelink_addr);
-int check_retouched(const char *fname, int elf_little,
- unsigned int *retouch_byte_cnt, char *retouch_buf);
-void retouch_dump(const char *fname, int elf_little,
- unsigned int retouch_byte_cnt, char *retouch_buf);
-void setup_prelink_info(const char *fname, int elf_little, long base);
-
-#endif
-#endif/*PRELINK_INFO_H*/
diff --git a/tools/soslim/soslim.c b/tools/soslim/soslim.c
deleted file mode 100644
index 33b1ee7..0000000
--- a/tools/soslim/soslim.c
+++ /dev/null
@@ -1,536 +0,0 @@
-#include <stdio.h>
-//#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <libebl.h>
-#include <libebl_arm.h>
-#include <elf.h>
-#include <gelf.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
-#include <prelink_info.h>
-#endif
-
-#include <elfcopy.h>
-
-void clone_elf(Elf *elf, Elf *newelf,
- const char *elf_name,
- const char *newelf_name,
- bool *sym_filter, int num_symbols,
- int shady
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- , int *prelinked,
- int *elf_little,
- long *prelink_addr,
- int *retouched,
- unsigned int *retouch_byte_cnt,
- char *retouch_buf
-#endif
- , bool rebuild_shstrtab,
- bool strip_debug,
- bool dry_run)
-{
- GElf_Ehdr ehdr_mem, *ehdr; /* store ELF header of original library */
- size_t shstrndx; /* section-strings-section index */
- size_t shnum; /* number of sections in the original file */
- /* string table for section headers in new file */
- struct Ebl_Strtab *shst = NULL;
- int dynamic_idx = -1; /* index in shdr_info[] of .dynamic section */
- int dynsym_idx = -1; /* index in shdr_info[] of dynamic symbol table
- section */
-
- unsigned int cnt; /* general-purpose counter */
- /* This flag is true when at least one section is dropped or when the
- relative order of sections has changed, so that section indices in
- the resulting file will be different from those in the original. */
- bool sections_dropped_or_rearranged;
- Elf_Scn *scn; /* general-purpose section */
- size_t idx; /* general-purporse section index */
-
- shdr_info_t *shdr_info = NULL;
- unsigned int shdr_info_len = 0;
- GElf_Phdr *phdr_info = NULL;
-
- /* Get the information from the old file. */
- ehdr = gelf_getehdr (elf, &ehdr_mem);
- FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
-
- /* Create new program header for the elf file */
- FAILIF(gelf_newehdr (newelf, gelf_getclass (elf)) == 0 ||
- (ehdr->e_type != ET_REL && gelf_newphdr (newelf,
- ehdr->e_phnum) == 0),
- "Cannot create new file: %s", elf_errmsg (-1));
-
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- ASSERT(prelinked);
- ASSERT(prelink_addr);
- ASSERT(elf_little);
- *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
- *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr);
- ASSERT(retouched);
- ASSERT(retouch_byte_cnt);
- ASSERT(retouch_buf);
- *retouched = check_retouched(elf_name, *elf_little,
- retouch_byte_cnt, retouch_buf);
-#endif
-
- INFO("\n\nCALCULATING MODIFICATIONS\n\n");
-
- /* Copy out the old program header: notice that if the ELF file does not
- have a program header, this loop won't execute.
- */
- INFO("Copying ELF program header...\n");
- phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum, sizeof(GElf_Phdr));
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) {
- INFO("\tRetrieving entry %d\n", cnt);
- FAILIF_LIBELF(NULL == gelf_getphdr(elf, cnt, phdr_info + cnt),
- gelf_getphdr);
- /* -- we update the header at the end
- FAILIF_LIBELF(gelf_update_phdr (newelf, cnt, phdr_info + cnt) == 0,
- gelf_update_phdr);
- */
- }
-
- /* Get the section-header strings section. This section contains the
- strings used to name the other sections. */
- FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0, elf_getshstrndx);
-
- /* Get the number of sections. */
- FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
- INFO("Original ELF file has %zd sections.\n", shnum);
-
- /* Allocate the section-header-info buffer. We allocate one more entry
- for the section-strings section because we regenerate that one and
- place it at the very end of the file. Note that just because we create
- an extra entry in the shdr_info array, it does not mean that we create
- one more section the header. We just mark the old section for removal
- and create one as the last section.
- */
- INFO("Allocating section-header info structure (%zd) bytes...\n",
- shnum*sizeof (shdr_info_t));
- shdr_info_len = rebuild_shstrtab ? shnum + 1 : shnum;
- shdr_info = (shdr_info_t *)CALLOC(shdr_info_len, sizeof (shdr_info_t));
-
- /* Iterate over all the sections and initialize the internal section-info
- array...
- */
- INFO("Initializing section-header info structure...\n");
- /* Gather information about the sections in this file. */
- scn = NULL;
- cnt = 1;
- while ((scn = elf_nextscn (elf, scn)) != NULL) {
- ASSERT(elf_ndxscn(scn) == cnt);
- shdr_info[cnt].scn = scn;
- FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr_info[cnt].shdr),
- gelf_getshdr);
-
- /* Get the name of the section. */
- shdr_info[cnt].name = elf_strptr (elf, shstrndx,
- shdr_info[cnt].shdr.sh_name);
-
- INFO("\tname: %s\n", shdr_info[cnt].name);
- FAILIF(shdr_info[cnt].name == NULL,
- "Malformed file: section %d name is null\n",
- cnt);
-
- /* Mark them as present but not yet investigated. By "investigating"
- sections, we mean that we check to see if by stripping other
- sections, the sections under investigation will be compromised. For
- example, if we are removing a section of code, then we want to make
- sure that the symbol table does not contain symbols that refer to
- this code, so we investigate the symbol table. If we do find such
- symbols, we will not strip the code section.
- */
- shdr_info[cnt].idx = 1;
-
- /* Remember the shdr.sh_link value. We need to remember this value
- for those sections that refer to other sections. For example,
- we need to remember it for relocation-entry sections, because if
- we modify the symbol table that a relocation-entry section is
- relative to, then we need to patch the relocation section. By the
- time we get to deciding whether we need to patch the relocation
- section, we will have overwritten its header's sh_link field with
- a new value.
- */
- shdr_info[cnt].old_shdr = shdr_info[cnt].shdr;
- INFO("\t\toriginal sh_link: %08d\n", shdr_info[cnt].old_shdr.sh_link);
- INFO("\t\toriginal sh_addr: %lld\n", shdr_info[cnt].old_shdr.sh_addr);
- INFO("\t\toriginal sh_offset: %lld\n",
- shdr_info[cnt].old_shdr.sh_offset);
- INFO("\t\toriginal sh_size: %lld\n", shdr_info[cnt].old_shdr.sh_size);
-
- if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) {
- INFO("\t\tthis is the SHT_DYNAMIC section [%s] at index %d\n",
- shdr_info[cnt].name,
- cnt);
- dynamic_idx = cnt;
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) {
- INFO("\t\tthis is the SHT_DYNSYM section [%s] at index %d\n",
- shdr_info[cnt].name,
- cnt);
- dynsym_idx = cnt;
- }
-
- FAILIF(shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX,
- "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n");
- FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP,
- "Cannot handle sh_type SHT_GROUP!\n");
- FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
- "Cannot handle sh_type SHT_GNU_versym!\n");
-
- /* Increment the counter. */
- ++cnt;
- } /* while */
-
- /* Get the EBL handling. */
- Ebl *ebl = ebl_openbackend (elf);
- FAILIF_LIBELF(NULL == ebl, ebl_openbackend);
- FAILIF_LIBELF(0 != arm_init(elf, ehdr->e_machine, ebl, sizeof(Ebl)),
- arm_init);
-
- if (strip_debug) {
-
- /* This will actually strip more than just sections. It will strip
- anything not essential to running the image.
- */
-
- INFO("Finding debug sections to strip.\n");
-
- /* Now determine which sections can go away. The general rule is that
- all sections which are not used at runtime are stripped out. But
- there are a few exceptions:
-
- - special sections named ".comment" and ".note" are kept
- - OS or architecture specific sections are kept since we might not
- know how to handle them
- - if a section is referred to from a section which is not removed
- in the sh_link or sh_info element it cannot be removed either
- */
- for (cnt = 1; cnt < shnum; ++cnt) {
- /* Check whether the section can be removed. */
- if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
- shdr_info[cnt].name,
- 1, /* remove .comment sections */
- 1 /* remove all debug sections */) ||
- /* The macro above is broken--check for .comment explicitly */
- !strcmp(".comment", shdr_info[cnt].name)
-#ifdef ARM_SPECIFIC_HACKS
- ||
- /* We ignore this section, that's why we can remove it. */
- !strcmp(".stack", shdr_info[cnt].name)
-#endif
- )
- {
- /* For now assume this section will be removed. */
- INFO("Section [%s] will be stripped from image.\n",
- shdr_info[cnt].name);
- shdr_info[cnt].idx = 0;
- }
-#ifdef STRIP_STATIC_SYMBOLS
- else if (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB) {
- /* Mark the static symbol table for removal */
- INFO("Section [%s] (static symbol table) will be stripped from image.\n",
- shdr_info[cnt].name);
- shdr_info[cnt].idx = 0;
- if (shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type ==
- SHT_STRTAB)
- {
- /* Mark the symbol table's string table for removal. */
- INFO("Section [%s] (static symbol-string table) will be stripped from image.\n",
- shdr_info[shdr_info[cnt].shdr.sh_link].name);
- shdr_info[shdr_info[cnt].shdr.sh_link].idx = 0;
- }
- else {
- ERROR("Expecting the sh_link field of a symbol table to point to"
- " associated symbol-strings table! This is not mandated by"
- " the standard, but is a common practice and the only way "
- " to know for sure which strings table corresponds to which"
- " symbol table!\n");
- }
- }
-#endif
- }
-
- /* Mark the SHT_NULL section as handled. */
- shdr_info[0].idx = 2;
-
- /* Handle exceptions: section groups and cross-references. We might have
- to repeat this a few times since the resetting of the flag might
- propagate.
- */
- int exceptions_pass = 0;
- bool changes;
- do {
- changes = false;
- INFO("\nHandling exceptions, pass %d\n\n", exceptions_pass++);
- for (cnt = 1; cnt < shnum; ++cnt) {
- if (shdr_info[cnt].idx == 0) {
- /* If a relocation section is marked as being removed but the
- section it is relocating is not, then do not remove the
- relocation section.
- */
- if ((shdr_info[cnt].shdr.sh_type == SHT_REL
- || shdr_info[cnt].shdr.sh_type == SHT_RELA)
- && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) {
- PRINT("\tSection [%s] will not be removed because the "
- "section it is relocating (%s) stays.\n",
- shdr_info[cnt].name,
- shdr_info[shdr_info[cnt].shdr.sh_info].name);
- }
- }
- if (shdr_info[cnt].idx == 1) {
- INFO("Processing section [%s]...\n", shdr_info[cnt].name);
-
- /* The content of symbol tables we don't remove must not
- reference any section which we do remove. Otherwise
- we cannot remove the referred section.
- */
- if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM ||
- shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
- {
- Elf_Data *symdata;
- size_t elsize;
-
- INFO("\tSection [%s] is a symbol table that's not being"
- " removed.\n\tChecking to make sure that no symbols"
- " refer to sections that are being removed.\n",
- shdr_info[cnt].name);
-
- /* Make sure the data is loaded. */
- symdata = elf_getdata (shdr_info[cnt].scn, NULL);
- FAILIF_LIBELF(NULL == symdata, elf_getdata);
-
- /* Go through all symbols and make sure the section they
- reference is not removed. */
- elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
-
- /* Check the length of the dynamic-symbol filter. */
- FAILIF(sym_filter != NULL &&
- (size_t)num_symbols != symdata->d_size / elsize,
- "Length of dynsym filter (%d) must equal the number"
- " of dynamic symbols (%zd)!\n",
- num_symbols,
- symdata->d_size / elsize);
-
- size_t inner;
- for (inner = 0;
- inner < symdata->d_size / elsize;
- ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym;
- size_t scnidx;
-
- sym = gelf_getsymshndx (symdata, NULL,
- inner, &sym_mem, NULL);
- FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);
-
- scnidx = sym->st_shndx;
- FAILIF(scnidx == SHN_XINDEX,
- "Can't handle SHN_XINDEX!\n");
- if (scnidx == SHN_UNDEF ||
- scnidx >= shnum ||
- (scnidx >= SHN_LORESERVE &&
- scnidx <= SHN_HIRESERVE) ||
- GELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- continue;
- }
-
- /* If the symbol is going to be thrown and it is a
- global or weak symbol that is defined (not imported),
- then continue. Since the symbol is going away, we
- do not care whether it refers to a section that is
- also going away.
- */
- if (sym_filter && !sym_filter[inner])
- {
- bool global_or_weak =
- ELF32_ST_BIND(sym->st_info) == STB_GLOBAL ||
- ELF32_ST_BIND(sym->st_info) == STB_WEAK;
- if (!global_or_weak && sym->st_shndx != SHN_UNDEF)
- continue;
- }
-
- /* -- far too much output
- INFO("\t\t\tSymbol [%s] (%d)\n",
- elf_strptr(elf,
- shdr_info[cnt].shdr.sh_link,
- sym->st_name),
- shdr_info[cnt].shdr.sh_info);
- */
-
- if (shdr_info[scnidx].idx == 0)
- {
- PRINT("\t\t\tSymbol [%s] refers to section [%s], "
- "which is being removed. Will keep that "
- "section.\n",
- elf_strptr(elf,
- shdr_info[cnt].shdr.sh_link,
- sym->st_name),
- shdr_info[scnidx].name);
- /* Mark this section as used. */
- shdr_info[scnidx].idx = 1;
- changes |= scnidx < cnt;
- }
- } /* for each symbol */
- } /* section type is SHT_DYNSYM or SHT_SYMTAB */
- /* Cross referencing happens:
- - for the cases the ELF specification says. That are
- + SHT_DYNAMIC in sh_link to string table
- + SHT_HASH in sh_link to symbol table
- + SHT_REL and SHT_RELA in sh_link to symbol table
- + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
- + SHT_GROUP in sh_link to symbol table
- + SHT_SYMTAB_SHNDX in sh_link to symbol table
- Other (OS or architecture-specific) sections might as
- well use this field so we process it unconditionally.
- - references inside section groups
- - specially marked references in sh_info if the SHF_INFO_LINK
- flag is set
- */
-
- if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0) {
- shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
- changes |= shdr_info[cnt].shdr.sh_link < cnt;
- }
-
- /* Handle references through sh_info. */
- if (SH_INFO_LINK_P (&shdr_info[cnt].shdr) &&
- shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) {
- PRINT("\tSection [%s] links to section [%s], which was "
- "marked for removal--it will not be removed.\n",
- shdr_info[cnt].name,
- shdr_info[shdr_info[cnt].shdr.sh_info].name);
-
- shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
- changes |= shdr_info[cnt].shdr.sh_info < cnt;
- }
-
- /* Mark the section as investigated. */
- shdr_info[cnt].idx = 2;
- } /* if (shdr_info[cnt].idx == 1) */
- } /* for (cnt = 1; cnt < shnum; ++cnt) */
- } while (changes);
- }
- else {
- INFO("Not stripping sections.\n");
- /* Mark the SHT_NULL section as handled. */
- shdr_info[0].idx = 2;
- }
-
- /* Mark the section header string table as unused, we will create
- a new one as the very last section in the new ELF file.
- */
- shdr_info[shstrndx].idx = rebuild_shstrtab ? 0 : 2;
-
- /* We need a string table for the section headers. */
- FAILIF_LIBELF((shst = ebl_strtabinit (1 /* null-terminated */)) == NULL,
- ebl_strtabinit);
-
- /* Assign new section numbers. */
- INFO("Creating new sections...\n");
- //shdr_info[0].idx = 0;
- for (cnt = idx = 1; cnt < shnum; ++cnt) {
- if (shdr_info[cnt].idx > 0) {
- shdr_info[cnt].idx = idx++;
-
- /* Create a new section. */
- FAILIF_LIBELF((shdr_info[cnt].newscn =
- elf_newscn(newelf)) == NULL, elf_newscn);
- ASSERT(elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
-
- /* Add this name to the section header string table. */
- shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
-
- INFO("\tsection [%s] (old offset %lld, old size %lld) will have index %d "
- "(was %zd).\n",
- shdr_info[cnt].name,
- shdr_info[cnt].old_shdr.sh_offset,
- shdr_info[cnt].old_shdr.sh_size,
- shdr_info[cnt].idx,
- elf_ndxscn(shdr_info[cnt].scn));
- } else {
- INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %zd), "
- "it will be discarded.\n",
- shdr_info[cnt].name,
- shdr_info[cnt].shdr.sh_offset,
- shdr_info[cnt].shdr.sh_size,
- elf_ndxscn(shdr_info[cnt].scn));
- }
- } /* for */
-
- sections_dropped_or_rearranged = idx != cnt;
-
- Elf_Data *shstrtab_data = NULL;
-
-#if 0
- /* Fail if sections are being dropped or rearranged (except for moving shstrtab) or the
- symbol filter is not empty, AND the file is an executable.
- */
- FAILIF(((idx != cnt && !(cnt - idx == 1 && rebuild_shstrtab)) || sym_filter != NULL) &&
- ehdr->e_type != ET_DYN,
- "You may not rearrange sections or strip symbols on an executable file!\n");
-#endif
-
- INFO("\n\nADJUSTING ELF FILE\n\n");
-
- adjust_elf(elf, elf_name,
- newelf, newelf_name,
- ebl,
- ehdr, /* store ELF header of original library */
- sym_filter, num_symbols,
- shdr_info, shdr_info_len,
- phdr_info,
- idx, /* highest_scn_num */
- shnum,
- shstrndx,
- shst,
- sections_dropped_or_rearranged,
- dynamic_idx, /* index in shdr_info[] of .dynamic section */
- dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
- shady,
- &shstrtab_data,
- ehdr->e_type == ET_DYN, /* adjust section ofsets only when the file is a shared library */
- rebuild_shstrtab);
-
- /* We have everything from the old file. */
- FAILIF_LIBELF(elf_cntl(elf, ELF_C_FDDONE) != 0, elf_cntl);
-
- /* The ELF library better follows our layout when this is not a
- relocatable object file. */
- elf_flagelf (newelf,
- ELF_C_SET,
- (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0));
-
- /* Finally write the file. */
- FAILIF_LIBELF(!dry_run && elf_update(newelf, ELF_C_WRITE) == -1, elf_update);
-
- if (shdr_info != NULL) {
- /* For some sections we might have created an table to map symbol
- table indices. */
- for (cnt = 1; cnt < shdr_info_len; ++cnt) {
- FREEIF(shdr_info[cnt].newsymidx);
- FREEIF(shdr_info[cnt].symse);
- if(shdr_info[cnt].dynsymst != NULL)
- ebl_strtabfree (shdr_info[cnt].dynsymst);
- }
- /* Free the memory. */
- FREE (shdr_info);
- }
- FREEIF(phdr_info);
-
- ebl_closebackend(ebl);
-
- /* Free other resources. */
- if (shst != NULL) ebl_strtabfree (shst);
- if (shstrtab_data != NULL)
- FREEIF(shstrtab_data->d_buf);
-}
diff --git a/tools/soslim/soslim.h b/tools/soslim/soslim.h
deleted file mode 100644
index 952c960..0000000
--- a/tools/soslim/soslim.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef ELFCOPY_H
-#define ELFCOPY_H
-
-#include <libelf.h>
-#include <libebl.h>
-#include <elf.h>
-#include <gelf.h>
-
-/*
-symbol_filter:
- On input: symbol_filter[i] indicates whether to keep a symbol (1) or to
- remove it from the symbol table.
- On output: symbol_filter[i] indicates whether a symbol was removed (0) or
- kept (1) in the symbol table.
-*/
-
-void clone_elf(Elf *elf, Elf *newelf,
- const char *elf_name,
- const char *newelf_name,
- bool *symbol_filter,
- int num_symbols,
- int shady
-#ifdef SUPPORT_ANDROID_PRELINK_TAGS
- , int *prelinked,
- int *elf_little,
- long *prelink_addr,
- int *retouched,
- unsigned int *retouch_byte_cnt,
- char *retouch_buf
-#endif
- , bool rebuild_shstrtab,
- bool strip_debug,
- bool dry_run);
-
-#endif/*ELFCOPY_H*/
diff --git a/tools/soslim/symfilter.c b/tools/soslim/symfilter.c
deleted file mode 100644
index b59e68a..0000000
--- a/tools/soslim/symfilter.c
+++ /dev/null
@@ -1,246 +0,0 @@
-#include <debug.h>
-#include <common.h>
-#include <symfilter.h>
-#include <hash.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <ctype.h>
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-static int match_hash_table_section(Elf *elf, Elf_Scn *sect, void *data);
-static int match_dynsym_section(Elf *elf, Elf_Scn *sect, void *data);
-
-void build_symfilter(const char *name, Elf *elf, symfilter_t *filter,
- off_t fsize)
-{
- char *line = NULL;
- symfilter_list_t *symbol;
-
- FAILIF(NULL == name,
- "You must provide a list of symbols to filter on!\n");
-
- filter->num_symbols = 0;
- filter->total_name_length = 0;
-
- /* Open the file. */
- INFO("Opening symbol-filter file %s...\n", name);
- filter->fd = open(name, O_RDONLY);
- FAILIF(filter->fd < 0, "open(%s): %s (%d)\n",
- name,
- strerror(errno),
- errno);
-
- INFO("Symbol-filter file %s is %zd bytes long...\n",
- name,
- (size_t)fsize);
- filter->fsize = fsize;
-
- /* mmap the symbols file */
- filter->mmap = mmap(NULL, fsize,
- PROT_READ | PROT_WRITE, MAP_PRIVATE,
- filter->fd, 0);
- FAILIF(MAP_FAILED == filter->mmap,
- "mmap(NULL, %zd, PROT_READ, MAP_PRIVATE, %d, 0): %s (%d)\n",
- (size_t)fsize,
- filter->fd,
- strerror(errno),
- errno);
- INFO("Memory-mapped symbol-filter file at %p\n", filter->mmap);
-
- /* Make sure that the ELF file has a hash table. We will use the hash
- table to look up symbols quickly. If the library does not have a hash-
- table section, we can still do a linear scan, but the code for that is
- not written, as practically every shared library has a hash table.
- */
-
- filter->symtab.sect = NULL;
- map_over_sections(elf, match_dynsym_section, filter);
- FAILIF(NULL == filter->symtab.sect,
- "There is no dynamic-symbol table in this library.\n");
- filter->hash.sect = NULL;
- map_over_sections(elf, match_hash_table_section, filter);
- FAILIF(NULL == filter->hash.sect,
- "There is no hash table in this library.\n");
- INFO("Hash table size 0x%lx, data size 0x%lx.\n",
- (unsigned long)filter->hash.hdr->sh_size,
- (unsigned long)filter->hash.data->d_size);
-
- INFO("Hash table file offset: 0x%x\n", filter->hash.hdr->sh_offset);
-
- GElf_Ehdr *ehdr, ehdr_mem;
- ehdr = gelf_getehdr(elf, &ehdr_mem);
- size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
- ASSERT(symsize);
- filter->num_symbols_to_keep = filter->symtab.data->d_size / symsize;
- filter->symbols_to_keep = (bool *)CALLOC(filter->num_symbols_to_keep,
- sizeof(bool));
-
- /* Build the symbol-name chain. */
- INFO("Building symbol list...\n");
-
- line = (char *)filter->mmap;
-
- filter->symbols = NULL;
-#define NOT_DONE ((off_t)(line - (char *)filter->mmap) < fsize)
- do {
- char *name = line;
-
- /* Advance to the next line. We seek out spaces or new lines. At the
- first space or newline character we find, we place a '\0', and
- continue till we've consumed the line. For new lines, we scan both
- '\r' and '\n'. For spaces, we look for ' ', '\t', and '\f'
- */
-
- while (NOT_DONE && !isspace(*line)) line++;
- if (likely(NOT_DONE)) {
- *line++ = '\0';
- if (line - name > 1) {
- /* Add the entry to the symbol-filter list */
- symbol = (symfilter_list_t *)MALLOC(sizeof(symfilter_list_t));
- symbol->next = filter->symbols;
- symbol->name = name;
- filter->symbols = symbol;
-
-#if 0
- /* SLOW! For debugging only! */
- {
- size_t idx;
- size_t elsize = gelf_fsize(elf, ELF_T_SYM, 1,
- ehdr->e_version);
- symbol->index = SHN_UNDEF;
- for (idx = 0; idx < filter->symtab.data->d_size / elsize;
- idx++) {
- GElf_Sym sym_mem;
- GElf_Sym *sym;
- const char *symname;
- sym = gelf_getsymshndx (filter->symtab.data, NULL,
- idx, &sym_mem, NULL);
- ASSERT(sym);
-
- symname = elf_strptr(elf,
- filter->symtab.hdr->sh_link,
- sym->st_name);
- if(!strcmp(symname, symbol->name)) {
- symbol->index = idx;
- break;
- }
- }
- }
-#else
- /* Look up the symbol in the ELF file and associate it with the
- entry in the filter. */
- symbol->index = hash_lookup(elf,
- &filter->hash,
- &filter->symtab,
- symbol->name,
- &symbol->symbol);
-#endif
- symbol->len = line - name - 1;
- ASSERT(symbol->len == strlen(symbol->name));
-
- /* If we didn't find the symbol, then it's not in the library.
- */
-
- if(STN_UNDEF == symbol->index) {
- PRINT("%s: symbol was not found!\n", symbol->name);
- }
- else {
- /* If we found the symbol but it's an undefined symbol, then
- it's not in the library as well. */
- GElf_Sym sym_mem;
- GElf_Sym *sym;
- sym = gelf_getsymshndx (filter->symtab.data, NULL,
- symbol->index, &sym_mem, NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- /* Make sure the hash lookup worked. */
- ASSERT(!strcmp(elf_strptr(elf,
- filter->symtab.hdr->sh_link,
- sym->st_name),
- symbol->name));
- if (sym->st_shndx == SHN_UNDEF) {
- PRINT("%s: symbol was not found (undefined)!\n", symbol->name);
- }
- else {
- filter->num_symbols++;
- /* Total count includes null terminators */
- filter->total_name_length += symbol->len + 1;
-
- /* Set the flag in the symbols_to_keep[] array. This indicates
- to function copy_elf() that we want to keep the symbol.
- */
- filter->symbols_to_keep[symbol->index] = true;
- INFO("FILTER-SYMBOL: [%s] [%d bytes]\n",
- symbol->name,
- symbol->len);
- }
- }
- }
- }
- } while (NOT_DONE);
-#undef NOT_DONE
-}
-
-void destroy_symfilter(symfilter_t *filter)
-{
- symfilter_list_t *old;
- INFO("Destroying symbol list...\n");
- while ((old = filter->symbols)) {
- filter->symbols = old->next;
- FREE(old);
- }
- munmap(filter->mmap, filter->fsize);
- close(filter->fd);
-}
-
-static int match_hash_table_section(Elf *elf, Elf_Scn *sect, void *data)
-{
- (void)elf; // unused argument
-
- symfilter_t *filter = (symfilter_t *)data;
- Elf32_Shdr *shdr;
-
- ASSERT(filter);
- ASSERT(sect);
- shdr = elf32_getshdr(sect);
-
- /* The section must be marked both as a SHT_HASH, and it's sh_link field
- must contain the index of our symbol table (per ELF-file spec).
- */
- if (shdr->sh_type == SHT_HASH)
- {
- FAILIF(filter->hash.sect != NULL,
- "There is more than one hash table!\n");
- get_section_info(sect, &filter->hash);
- }
-
- return 0; /* keep looking */
-}
-
-static int match_dynsym_section(Elf *elf, Elf_Scn *sect, void *data)
-{
- (void)elf; // unused argument
-
- symfilter_t *filter = (symfilter_t *)data;
- Elf32_Shdr *shdr;
-
- ASSERT(filter);
- ASSERT(sect);
- shdr = elf32_getshdr(sect);
-
- if (shdr->sh_type == SHT_DYNSYM)
- {
- FAILIF(filter->symtab.sect != NULL,
- "There is more than one dynamic symbol table!\n");
- get_section_info(sect, &filter->symtab);
- }
-
- return 0; /* keep looking */
-}
diff --git a/tools/soslim/symfilter.h b/tools/soslim/symfilter.h
deleted file mode 100644
index f73fd50..0000000
--- a/tools/soslim/symfilter.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef SYMFILTER_H
-#define SYMFILTER_H
-
-/* This file describes the interface for parsing the list of symbols. Currently,
- this is just a text file with each symbol on a separate line. We build an
- in-memory linked list of symbols out of this image.
-*/
-
-#include <stdio.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <libebl.h> /* defines bool */
-
-typedef struct symfilter_list_t symfilter_list_t;
-struct symfilter_list_t {
- symfilter_list_t *next;
- const char *name;
- unsigned int len; /* strlen(name) */
- Elf32_Word index;
- GElf_Sym symbol;
-};
-
-typedef struct symfilter_t {
-
- int fd; /* symbol-filter-file descriptor */
- off_t fsize; /* size of file */
- void *mmap; /* symbol-fiter-file memory mapping */
-
- section_info_t symtab;
- section_info_t hash;
- symfilter_list_t *symbols;
-
- /* The total number of symbols in the symfilter. */
- unsigned int num_symbols;
- /* The total number of bytes occupied by the names of the symbols, including
- the terminating null characters.
- */
- unsigned int total_name_length;
-
- bool *symbols_to_keep;
- /* must be the same as the number of symbols in the dynamic table! */
- int num_symbols_to_keep;
-} symfilter_t;
-
-void build_symfilter(const char *name, Elf *elf, symfilter_t *filter, off_t);
-void destroy_symfilter(symfilter_t *);
-
-#endif/*SYMFILTER_H*/