Initial commit
This commit is contained in:
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
call_to=bfd
|
||||
|
||||
case "${CTNG_LD_IS}" in
|
||||
bfd) call_to=bfd;;
|
||||
gold) call_to=gold;;
|
||||
esac
|
||||
|
||||
exec "${0}.${call_to}" "$@"
|
||||
exit $?
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,472 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# NON-CONFIGURABLE STUFF!
|
||||
export LC_ALL=C
|
||||
version="1.26.0.155_62fb594"
|
||||
bits="32"
|
||||
sed="${SED:-sed}"
|
||||
grep="${GREP:-grep}"
|
||||
|
||||
my_name="$( basename "${0}" )"
|
||||
prefix="${0%-ldd}"
|
||||
gcc="${prefix}-gcc"
|
||||
readelf="${prefix}-readelf"
|
||||
fake_load_addr_root="$((0xdeadbeef))"
|
||||
fake_load_addr_rpath="$((0xdeadc0de))"
|
||||
fake_load_addr_sysroot="$((0x8badf00d))"
|
||||
ld_library_path="/lib:/usr/lib"
|
||||
|
||||
need_e_class=
|
||||
need_e_flags=
|
||||
need_e_mach=
|
||||
|
||||
do_error() {
|
||||
printf "%s: %s\n" "${my_name}" "$*" >&2
|
||||
}
|
||||
|
||||
do_opt_error() {
|
||||
do_error "$@"
|
||||
printf "Try \`%s --help' for more information\n" "${my_name}" >&2
|
||||
}
|
||||
|
||||
do_trace() {
|
||||
local depth=0
|
||||
|
||||
[ -z "${CT_XLDD_VERBOSE}" ] && return 0
|
||||
|
||||
for((depth=0; "${#FUNCNAME[$((depth+1))]}" != 0; depth++)); do :; done
|
||||
printf "%*s" $((4*(depth-1))) "" >&2
|
||||
printf -- "$@" >&2
|
||||
}
|
||||
|
||||
show_version() {
|
||||
# Fake a real ldd, just in case some dumb script would check
|
||||
cat <<_EOF_
|
||||
ldd (crosstool-NG) ${version}
|
||||
Copyright (C) 2010 "Yann E. MORIN" <yann.morin.1998@free.fr>
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
Licensed under the GPLv2, see the file LICENSE in the top-directory of the
|
||||
sources for this package.
|
||||
_EOF_
|
||||
}
|
||||
|
||||
show_help() {
|
||||
cat <<_EOF_
|
||||
Usage: ${my_name} [OPTION]... --root DIR FILE...
|
||||
--help print this help and exit
|
||||
--version print version information and exit
|
||||
--root dir treat dir as being the root of the target
|
||||
-s, --show-system mark libs from the sysroot with a trailing '[*]'
|
||||
and libs found via RPATH with a trailing '[+]'
|
||||
|
||||
_EOF_
|
||||
cat <<_EOF_ |fmt
|
||||
${my_name} tries to mimick the behavior of a real native ldd, but can be
|
||||
used in a cross-development environment. Here is how it differs from a
|
||||
real native ldd:
|
||||
|
||||
If the CT_XLDD_VERBOSE variable is set and non-empty, then ${my_name} will
|
||||
print a lot of debug messages, explaining how it builds the library
|
||||
search path, and how each library was found and why.
|
||||
|
||||
The LD_LIBRARY_PATH variable is not used, as it can not reliably be
|
||||
guessed except at runtime, and we can't run.
|
||||
|
||||
${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
|
||||
(it understands the include directives therein for libces that have that).
|
||||
|
||||
${my_name} also interprets (tries to!) the RPATH/RUNPATH records found in
|
||||
the dynamic ELF section. Such paths are searched for only relative to
|
||||
the specified root, not from the sysroot (see below). Also, those paths
|
||||
are searched for not only for the file they appear in, but also for its
|
||||
dependencies.
|
||||
|
||||
${my_name} will search the directory specified with --root for libraries
|
||||
to resolve the NEEDED tags. If --root is not set, then ${my_name} will
|
||||
use the value in the environment variable \${CT_XLDD_ROOT}. If neither
|
||||
is set, then this is an error.
|
||||
|
||||
If NEEDED libraries can't be found in the specified root directory, then
|
||||
${my_name} will also look in the sysroot of the toolchain to see if it
|
||||
can find them.
|
||||
|
||||
For NEEDED libraries that were found, the output will look like:
|
||||
libneeded.so => /path/to/libneeded.so (0xloadaddr)
|
||||
|
||||
and for those that were not found, the output will look like:
|
||||
libneeded.so not found
|
||||
|
||||
The paths are relative to the specified root directory, or to the sysroot
|
||||
(eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...).
|
||||
|
||||
The expected load address 'loadaddr' is a faked address to match the output
|
||||
of the real ldd, but has no actual meaning (set to some constants for now,
|
||||
0x8badf00d for libraries from the sysroot, 0xdeadc0de for those found via
|
||||
the RPATH/RUNPATH records, and 0xdeadbeef for others).
|
||||
_EOF_
|
||||
|
||||
# Unimplemeted yet:
|
||||
# -d, --data-relocs process data relocations
|
||||
# -r, --function-relocs process data and function relocations
|
||||
# -u, --unused print unused direct dependencies
|
||||
# -v, --verbose print all information
|
||||
|
||||
# See also this thread:
|
||||
# http://sourceware.org/ml/crossgcc/2008-09/msg00057.html
|
||||
}
|
||||
|
||||
# Parse command line options
|
||||
root="${CT_XLDD_ROOT}"
|
||||
show_system=
|
||||
while true; do
|
||||
case "${1}" in
|
||||
--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
--version)
|
||||
show_version
|
||||
exit 0
|
||||
;;
|
||||
--root)
|
||||
root="$2"
|
||||
shift
|
||||
;;
|
||||
--root=*)
|
||||
root="${1#--root=}"
|
||||
;;
|
||||
--show-system|-s)
|
||||
show_system=1
|
||||
;;
|
||||
-*)
|
||||
do_opt_error "unrecognized option \`${1}'"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Sanity checks
|
||||
if [ -z "${root}" ]; then
|
||||
do_opt_error "no root given"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "${root}" ]; then
|
||||
do_error "\`${root}': no such file or directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )"
|
||||
if [ -z "${sysroot}" ]; then
|
||||
sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \
|
||||
|${sed} -r -e 's:/usr/lib/libc.so$::;' \
|
||||
)"
|
||||
fi
|
||||
if [ -z "${sysroot}" ]; then
|
||||
do_error "unable to find sysroot for \`${gcc}'"
|
||||
fi
|
||||
|
||||
do_report_needed_found() {
|
||||
local needed="${1}"
|
||||
local path="${2}"
|
||||
local origin="${3}"
|
||||
local loadaddr
|
||||
local sys
|
||||
|
||||
case "${origin}" in
|
||||
root)
|
||||
loadaddr="${fake_load_addr_root}"
|
||||
;;
|
||||
rpath)
|
||||
loadaddr="${fake_load_addr_rpath}"
|
||||
if [ -n "${show_system}" ]; then
|
||||
sys=" [+]"
|
||||
fi
|
||||
;;
|
||||
sysroot)
|
||||
loadaddr="${fake_load_addr_sysroot}"
|
||||
if [ -n "${show_system}" ]; then
|
||||
sys=" [*]"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
printf "%8s%s => %s (0x%0*x)%s\n" \
|
||||
"" \
|
||||
"${needed}" \
|
||||
"${path}" \
|
||||
"$((bits/4))" \
|
||||
"${loadaddr}" \
|
||||
"${sys}"
|
||||
}
|
||||
|
||||
# Helper: passed flags and needed flags must either both have
|
||||
# a given flag set, or neither must have it.
|
||||
flag_match() {
|
||||
local flags="${1}"
|
||||
local e_flags="${2}"
|
||||
local dso="${3}"
|
||||
local f
|
||||
|
||||
for f in ${flags}; do
|
||||
case "${e_flags}:${need_e_flags}" in
|
||||
*,${f},*:*,${f},*)
|
||||
# Both have it, continue
|
||||
;;
|
||||
*,${f},*)
|
||||
# Only one has it
|
||||
do_trace "-> skip incompatible '%s' (flags '%s', need '%s')" \
|
||||
"${dso}" "${e_flags}" "${need_e_flags}"
|
||||
return 1;;
|
||||
*) ;; # Neither one has it, continue
|
||||
esac
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
__warned_unknown_machine=no
|
||||
do_check_compat() {
|
||||
local file="${1}"
|
||||
local info e_mach e_class e_flags
|
||||
local dso
|
||||
local -a flags
|
||||
|
||||
if [ ! -r "${file}" ]; then
|
||||
return 1
|
||||
fi
|
||||
info=`${readelf} -Wh "${file}"`
|
||||
e_class=`echo "${info}" | "${sed}" -nr 's/.*Class:[[:space:]]*//p'`
|
||||
e_mach=`echo "${info}" | "${sed}" -nr 's/.*Machine:[[:space:]]*//p'`
|
||||
e_flags=`echo "${info}" | "${sed}" -nr -e 's/$/,/' -e 's/, /,/g' -e 's/.*Flags:[[:space:]]*0x[0-9a-f]{1,}//p'`
|
||||
dso="${base}${d}/${needed}"
|
||||
if [ "${e_class}" != "${need_e_class}" ]; then
|
||||
do_trace "-> skip incompatible '%s' (class '%s', need '%s')\n" \
|
||||
"${dso}" "${e_class}" "${need_e_class}"
|
||||
return 1
|
||||
fi
|
||||
if [ "${e_mach}" != "${need_e_mach}" ]; then
|
||||
do_trace "-> skip incompatible '%s' (machine '%s', need '%s')\n" \
|
||||
"${dso}" "${e_mach}" "${need_e_mach}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ElfXX_Ehdr.e_flags is trickier, the rules for compatibility are
|
||||
# different for different architectures (machines). The logic is
|
||||
# the same as in elf_machine_matches_host() in GNU libc.
|
||||
case "${e_mach}" in
|
||||
AArch64|"Advanced Micro Devices X86-64"|Alpha|ARM|"Intel 80386"|\
|
||||
MC68000|"Xilinx MicroBlaze"|"Altera Nios II"|"Renesas / SuperH SH")
|
||||
# Simple cases: flags are not taken into the account
|
||||
;;
|
||||
"MIPS R3000")
|
||||
# glibc just rejects "fp64", says it is unsupported on linux.
|
||||
# but who knows, maybe one day ct-ng will be targeting non-linux too.
|
||||
if ! flag_match "abi2 nan2008 fp64" "${e_flags}" "${dso}"; then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
PowerPC)
|
||||
# For 32-bit PowerPC, flags not checked. For 64-bit, check ABI version:
|
||||
# 0 means "not using any features affected by the differences"; v1 and v2
|
||||
# are the defined ABI versions. Here we have a different check than glibc:
|
||||
# in glibc, the dynamic linker checks the ABI compatibility against its own
|
||||
# ABI while we here check against the binary ABI. Doing it properly requires
|
||||
# a rework of this script, and the current check seems to work even with a
|
||||
# trivial "hello world" (it is reported as "abiv1", so apparently no
|
||||
# applications report 0 as ABI version).
|
||||
if [ "${e_class}" = "ELF64" ] && ! flag_match "abiv1 abiv2" "${e_flags}" "${dso}"; then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
"IBM S/390")
|
||||
# Dynamic linker checks against the kernel capability for "highgprs" flag
|
||||
# at runtime, but we cannot do that. Report success.
|
||||
;;
|
||||
Sparc|"Sparc v8+"|"Sparc v9")
|
||||
# According to glibc sources, even DSOs reporting these different e_machine
|
||||
# values may be compatible. We currently don't handle that, but might need to.
|
||||
;;
|
||||
*)
|
||||
# Warn once on an unhandled architecture and assume flags are compatible
|
||||
if [ "${__warned_unknown_machine}" = "no" ]; then
|
||||
__warned_unknown_machine=yes
|
||||
do_error "Architecture ${e_mach} not handled by cross-ldd script; assuming match"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
# Search a needed file, scanning ${lib_dir} in the root directory
|
||||
do_find_needed() {
|
||||
local needed="${1}"
|
||||
local -a list
|
||||
local -a dirs
|
||||
local found
|
||||
local where
|
||||
local base
|
||||
local d i
|
||||
|
||||
do_trace "Searching for '%s'\n" "${needed}"
|
||||
|
||||
# rpath shall come first!
|
||||
list=( \
|
||||
"rpath:${root}" \
|
||||
"root:${root}" \
|
||||
"sysroot:${sysroot}" \
|
||||
)
|
||||
|
||||
for i in "${list[@]}"; do
|
||||
where="${i%%:*}"
|
||||
base="${i#*:}"
|
||||
if [ "${where}" = "rpath" ]; then
|
||||
dirs=( "${search_rpath[@]}" )
|
||||
else
|
||||
dirs=( "${needed_search_path[@]}" )
|
||||
fi
|
||||
for d in "${dirs[@]}"; do
|
||||
do_trace "-> looking in '%s' (%s)\n" "${d}" "${where}"
|
||||
if do_check_compat "${base}${d}/${needed}"; then
|
||||
found="${d}/${needed}"
|
||||
do_trace "---> found\n"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [ -n "${found}" ]; then
|
||||
do_report_needed_found "${needed}" "${found}" "${where}"
|
||||
do_process_file "${base}${found}"
|
||||
else
|
||||
printf "%8s%s not found\n" "" "${needed}"
|
||||
fi
|
||||
|
||||
do_trace "Done searching for '%s'\n" "${needed}"
|
||||
}
|
||||
|
||||
# Scan a file for all NEEDED tags
|
||||
do_process_file() {
|
||||
local file="${1}"
|
||||
local initial="${2}"
|
||||
local -a save_search_rpath
|
||||
local n m
|
||||
local found
|
||||
local info
|
||||
|
||||
do_trace "Parsing file '%s'\n" "${file}"
|
||||
|
||||
save_search_rpath=( "${search_rpath[@]}" )
|
||||
for n in $( "${readelf}" -d "${file}" \
|
||||
|"${grep}" -E '\((RPATH|RUNPATH)\)' \
|
||||
|"${sed}" -r -e 's/^.*Library r(|un)path:[[:space:]]+\[(.*)\]$/\2/;'\
|
||||
); do
|
||||
do_trace "-> adding rpath '%s'\n" "${n}"
|
||||
search_rpath+=( "${n}" )
|
||||
done
|
||||
do_trace ": search path:\n"
|
||||
for n in "${search_rpath[@]}" "${needed_search_path[@]}"; do
|
||||
do_trace ": - '%s'\n" "${n}"
|
||||
done
|
||||
do_trace ": end search path\n"
|
||||
|
||||
if [ -n "${initial}" ]; then
|
||||
if ! "${readelf}" -Wl "${file}" |
|
||||
"${grep}" 'Requesting program interpreter: ' >/dev/null; then
|
||||
printf " not a dynamic executable\n"
|
||||
exit 1
|
||||
fi
|
||||
info=`${readelf} -Wh "${file}"`
|
||||
need_e_class=`echo "${info}" | "${sed}" -nr 's/.*Class:[[:space:]]*//p'`
|
||||
need_e_mach=`echo "${info}" | "${sed}" -nr 's/.*Machine:[[:space:]]*//p'`
|
||||
need_e_flags=`echo "${info}" | "${sed}" -nr -e 's/$/,/' -e 's/, /,/g' -e 's/.*Flags:[[:space:]]*0x[0-9a-f]{1,}//p'`
|
||||
fi
|
||||
for n in $( "${readelf}" -d "${file}" \
|
||||
|"${grep}" -E '\(NEEDED\)' \
|
||||
|"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[([^]]+)\].*/\1/;' \
|
||||
); do
|
||||
found=0
|
||||
for m in "${needed_list[@]}"; do
|
||||
[ "${n}" = "${m}" ] && found=1 && break
|
||||
done
|
||||
if [ ${found} -ne 0 ]; then
|
||||
do_trace "-> skipping already known dependency '%s'\n" "${n}"
|
||||
continue
|
||||
fi
|
||||
do_trace "-> handling new dependency '%s'\n" "${n}"
|
||||
needed_list+=( "${n}" )
|
||||
do_find_needed "${n}"
|
||||
do_trace "-> done handling dependency '%s'\n" "${n}"
|
||||
done
|
||||
|
||||
search_rpath=( "${save_search_rpath[@]}" )
|
||||
|
||||
do_trace "Finished parsing file '%s'\n" "${file}"
|
||||
}
|
||||
|
||||
# Recursively scan a /etc/ld.so.conf file
|
||||
do_scan_etc_ldsoconf() {
|
||||
local ldsoconf="${1}"
|
||||
local g
|
||||
local f
|
||||
|
||||
[ -f "${ldsoconf}" ] || return 0
|
||||
do_trace "Parsing ld.so.conf: '%s'\n" "${ldsoconf}"
|
||||
|
||||
while read line; do
|
||||
case "${line}" in
|
||||
include\ *)
|
||||
g="${root}${line#include }"
|
||||
do_trace "-> handling include directive '%s'\n" "${g}"
|
||||
for f in ${g}; do
|
||||
do_scan_etc_ldsoconf "${f}"
|
||||
done
|
||||
do_trace "-> finished handling include directive '%s'\n" "${g}"
|
||||
;;
|
||||
\#*|"")
|
||||
;;
|
||||
*)
|
||||
do_trace "-> adding search dir '%s'\n" "${line}"
|
||||
needed_search_path+=( "${line}" )
|
||||
;;
|
||||
esac
|
||||
done <"${ldsoconf}"
|
||||
|
||||
do_trace "Finished parsing ld.so.conf: '%s'\n" "${ldsoconf}"
|
||||
}
|
||||
|
||||
if [ -z "${1}" ]; then
|
||||
show_help
|
||||
elif [ ! -r "${1}" ]; then
|
||||
do_error "${1}: No such file or directory"
|
||||
fi
|
||||
|
||||
# Build up the full list of search directories
|
||||
declare -a needed_search_path
|
||||
do_trace "Adding basic lib dirs\n"
|
||||
ld_library_path="${ld_library_path}:"
|
||||
while [ -n "${ld_library_path}" ]; do
|
||||
d="${ld_library_path%%:*}"
|
||||
if [ -n "${d}" ]; then
|
||||
do_trace "-> adding search dir '%s'\n" "${d}"
|
||||
needed_search_path+=( "${d}" )
|
||||
fi
|
||||
ld_library_path="${ld_library_path#*:}"
|
||||
done
|
||||
do_trace "Done adding basic lib dirs\n"
|
||||
do_trace "Scanning '/etc/ld.so.conf'\n"
|
||||
do_scan_etc_ldsoconf "${root}/etc/ld.so.conf"
|
||||
do_trace "Done scanning '/etc/ld.so.conf'\n"
|
||||
do_trace "Search path:\n"
|
||||
for p in "${needed_search_path[@]}"; do
|
||||
do_trace "-> '%s'\n" "${p}"
|
||||
done
|
||||
|
||||
declare -a needed_list
|
||||
declare -a search_rpath
|
||||
do_trace "Scanning file '%s'\n" "${1}"
|
||||
do_process_file "${1}" initial
|
||||
do_trace "Done scanning file '%s'\n" "${1}"
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+298
@@ -0,0 +1,298 @@
|
||||
#!/bin/sh
|
||||
# This script will populate the root directory with libs from the sysroot.
|
||||
# (C) 2007 Yann E. MORIN
|
||||
# Licensed under the GPL v2
|
||||
set -e
|
||||
|
||||
# Use the tools discovered by crosstool-NG's ./configure:
|
||||
install="install"
|
||||
grep="grep"
|
||||
sed="sed"
|
||||
awk="awk"
|
||||
|
||||
# Detect where the toolchain is:
|
||||
CT_PREFIX_DIR="$(cd "$(dirname "$0")/.."; pwd)"
|
||||
CT_GCC="${0%-populate}-gcc"
|
||||
CT_READELF="${0%-populate}-readelf"
|
||||
CT_CFG_PREFIX_DIR="$("${CT_GCC}" -v 2>&1 \
|
||||
|tr ' ' '\n' \
|
||||
|"${grep}" -E -- '--prefix=' \
|
||||
|cut -d = -f 2-
|
||||
)"
|
||||
CT_CFG_SYSROOT_DIR="$("${CT_GCC}" -v 2>&1 \
|
||||
|tr ' ' '\n' \
|
||||
|"${grep}" -E -- '--with-sysroot=' \
|
||||
|cut -d = -f 2-
|
||||
)"
|
||||
CT_SYSROOT_DIR="$(printf "${CT_CFG_SYSROOT_DIR}\n" \
|
||||
|"${sed}" -r -e "s:^${CT_CFG_PREFIX_DIR}:${CT_PREFIX_DIR}:;" \
|
||||
|"${sed}" -r -e 's,/+,/,g;' \
|
||||
)"
|
||||
|
||||
myname=$(basename "$0")
|
||||
|
||||
doHelp() {
|
||||
cat <<_EOF_
|
||||
NAME
|
||||
$myname - populate the target root file system
|
||||
|
||||
SYNOPSIS
|
||||
$myname OPTIONS -s source_root -d destination_root
|
||||
|
||||
DESCRIPTION
|
||||
This script will 'populate' your target root file system 'source_root'
|
||||
with libraries from the toolchain (eg. libc.so...), storing the result
|
||||
into 'dst_dir'.
|
||||
|
||||
OPTIONS
|
||||
-s src_dir
|
||||
Use 'src_dir' as the un-populated (source) root directory.
|
||||
|
||||
-d dst_dir
|
||||
Use 'dst_dir' as the place to put the populated root directory.
|
||||
See the -f and -m options, below, on the required (non-)existence
|
||||
of this directory.
|
||||
|
||||
-r sysroot_dir
|
||||
Use 'sysroot_dir' as the sysroot instead of the toolchain default.
|
||||
|
||||
-l name1[:name2[...]]
|
||||
Always add the specified shared library/ies name1, name2... from the
|
||||
toolchain (in the sysroot). Actual library names are searched as
|
||||
follows (where 'name' is replaced with the given name) in the
|
||||
sysroot directory:
|
||||
- libname.so
|
||||
- name.so
|
||||
- name
|
||||
If the file is found, then the SONAME of the library is used, and the
|
||||
library is copied with that name. If the library was not found, this
|
||||
yields an error (unless -f was given).
|
||||
|
||||
-L file
|
||||
Read 'file' for a list of shared libraries to always add from the
|
||||
toolchain. The file should contain one library name per line; text
|
||||
after a # is ignored until the end of the line; spaces are ignored;
|
||||
empty lines are ignored. Libraries are searched for as with -l.
|
||||
|
||||
-f Force execution: if destination directory already exists, it will be
|
||||
removed first; if a specified library (above) was not found, continue.
|
||||
Note: if using -m and the destination directory already exists, it
|
||||
is *not* removed, see below.
|
||||
|
||||
-m Merge the source root directory with the destination root directory.
|
||||
If the latter does not exist, it is created, and -m is ignored.
|
||||
If the destination root directory exists, then the content of the
|
||||
source root directory is copied in there, and the result is populated
|
||||
as usual.
|
||||
It can be useful if constructing a rootfs incrementally from many
|
||||
smaller source root directories, or if your destination root directory
|
||||
is an NFS export that your target mounts as / (and you don't want to
|
||||
re-run exportfs -av everytime). USE WITH CARE!
|
||||
|
||||
-v Be verbose. By default, populate is absolutely silent.
|
||||
|
||||
_EOF_
|
||||
}
|
||||
|
||||
CT_ROOT_SRC_DIR=
|
||||
CT_ROOT_DST_DIR=
|
||||
CT_LIB_LIST=
|
||||
CT_LIB_FILE=
|
||||
CT_MERGE=
|
||||
CT_FORCE=
|
||||
CT_PRINTF=:
|
||||
OPTIND=1
|
||||
while getopts ":s:d:r:l:L:fmvh" CT_OPT; do
|
||||
case "${CT_OPT}" in
|
||||
s) CT_ROOT_SRC_DIR="${OPTARG}";;
|
||||
d) CT_ROOT_DST_DIR="${OPTARG}";;
|
||||
r) CT_SYSROOT_DIR="${OPTARG}";;
|
||||
l) CT_LIB_LIST="${CT_LIB_LIST}:${OPTARG}";;
|
||||
L) CT_LIB_FILE="${OPTARG}";;
|
||||
f) CT_FORCE=y;;
|
||||
m) CT_MERGE=y;;
|
||||
v) CT_PRINTF=printf;;
|
||||
h) doHelp
|
||||
exit 0
|
||||
;;
|
||||
:) printf "$myname: '-${OPTARG}' takes exactly one argument.\n"
|
||||
exit 1
|
||||
;;
|
||||
?) printf "$myname: unknown option '-${OPTARG}'.\n"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Sanity checks
|
||||
if [ -z "${CT_ROOT_SRC_DIR}" -o -z "${CT_ROOT_DST_DIR}" ]; then
|
||||
doHelp
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "${CT_ROOT_SRC_DIR}" ]; then
|
||||
printf "$myname: '${CT_ROOT_SRC_DIR}': no such file or directory\n"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "${CT_SYSROOT_DIR}" ]; then
|
||||
printf "$myname: '${CT_SYSROOT_DIR}': no such file or directory\n"
|
||||
exit 1
|
||||
fi
|
||||
# If the dest dir does not exist, all is well
|
||||
# If merging, we accept an existing dest directory
|
||||
# If forcing and not merging, we remove an exiting dest directory
|
||||
# If not forcing and not merging, we do not accept an exiting dest directory
|
||||
if [ -d "${CT_ROOT_DST_DIR}" ]; then
|
||||
case "${CT_FORCE}:${CT_MERGE}" in
|
||||
*:y) ;;
|
||||
y:) rm -rf "${CT_ROOT_DST_DIR}";;
|
||||
:) printf "$myname: '${CT_ROOT_DST_DIR}': already exists\n"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
src_inode=$(ls -1id "${CT_ROOT_SRC_DIR}/." |${awk} '{ print $1 }')
|
||||
dst_inode=$(ls -1id "${CT_ROOT_DST_DIR}/." 2>/dev/null |${awk} '{ print $1 }')
|
||||
if [ "${src_inode}" -eq "$((dst_inode+0))" ]; then
|
||||
printf "$myname: source and destination are the same!\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check existence of the forced libraries file
|
||||
if [ -n "${CT_LIB_FILE}" -a ! \( -f "${CT_LIB_FILE}" -a -r "${CT_LIB_FILE}" \) ]; then
|
||||
printf "$myname: forced libraries file '${CT_LIB_FILE}' not found!\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the working copy, no issue if already existing
|
||||
mkdir -p "${CT_ROOT_DST_DIR}"
|
||||
|
||||
# Make all path absolute
|
||||
CT_ROOT_SRC_DIR=$(cd "${CT_ROOT_SRC_DIR}"; pwd)
|
||||
CT_ROOT_DST_DIR=$(cd "${CT_ROOT_DST_DIR}"; pwd)
|
||||
CT_SYSROOT_DIR=$(cd "${CT_SYSROOT_DIR}"; pwd)
|
||||
|
||||
# Populate the destination directory with files from the source directory
|
||||
cd "${CT_ROOT_SRC_DIR}"
|
||||
cp -a . "${CT_ROOT_DST_DIR}"
|
||||
cd - >/dev/null
|
||||
|
||||
# A function do search for a library
|
||||
# Usage: do_add_lib libname
|
||||
# returns: 0 if library was found and added, !0 otherwise
|
||||
do_add_lib() {
|
||||
local libname="$1"
|
||||
local true_libname
|
||||
local dir
|
||||
local mode
|
||||
|
||||
for dir in lib usr/lib usr/lib/gconv; do
|
||||
if [ -e "${dir}/${libname}" ]; then
|
||||
${CT_PRINTF} " already present\n"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
for dir in lib usr/lib usr/lib/gconv; do
|
||||
${CT_PRINTF} " trying in '%s'" "${dir}"
|
||||
libfile="${CT_SYSROOT_DIR}/${dir}/${libname}"
|
||||
${CT_PRINTF} ": '%s'\n" "${libfile}"
|
||||
if [ -e "${libfile}" ]; then
|
||||
mkdir -p "${dir}"
|
||||
true_libname=$("${CT_READELF}" -d "${libfile}" \
|
||||
|"${grep}" "Library soname:" \
|
||||
|"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;' \
|
||||
)
|
||||
case "${libfile}" in
|
||||
*/ld*) mode=0755;;
|
||||
*) mode=0644;;
|
||||
esac
|
||||
${CT_PRINTF} " installing as '%s/%s', mode='%s'\n" "${dir}" "${true_libname}" "${mode}"
|
||||
${install} -m "${mode}" "${libfile}" "${dir}/${true_libname}"
|
||||
do_resolve_deps "${dir}/${true_libname}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# A function to resolve all NEEDED entries for the given file, relative
|
||||
# to the working directory (eg. dst_dir)
|
||||
# Usage: do_resolve_deps some/where/some/file
|
||||
# Returns: 0, meaning all dependencies were found
|
||||
# If not all dependencies could be found, exists with error code 1
|
||||
# (unless forced)
|
||||
do_resolve_deps() {
|
||||
local file="${1}"
|
||||
local libname
|
||||
|
||||
for libname in $("${CT_READELF}" -d "${file}" \
|
||||
|"${grep}" -E '\(NEEDED\)[[:space:]]+Shared library:' \
|
||||
|"${sed}" -r -e 's,.+\[(.+)\] *$,\1,;' \
|
||||
); do
|
||||
[ -n "${libname}" ] || continue
|
||||
${CT_PRINTF} "Searching for '%s' needed by '%s'\n" "${libname}" "${file}"
|
||||
if ! do_add_lib "${libname}"; then
|
||||
printf "$myname: library '${libname}' not found!\n"
|
||||
[ "${CT_FORCE}" = "y" ] || exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# We'll work in the copied rootfs
|
||||
cd "${CT_ROOT_DST_DIR}"
|
||||
|
||||
# First of, copy the forced libraries into the working copy
|
||||
lib_list=
|
||||
if [ -n "${CT_LIB_FILE}" ]; then
|
||||
lib_list=$("${sed}" -r -e ':loop; s/#.*//;' \
|
||||
-e 's/[[:space:]]+//g;' \
|
||||
-e 's/([^:])$/\1:/;' \
|
||||
-e '/$/N; s/\n//; tloop;' \
|
||||
"${CT_LIB_FILE}"
|
||||
)
|
||||
fi
|
||||
CT_LIB_LIST=$(printf "${CT_LIB_LIST}:${lib_list}\n" \
|
||||
|"${sed}" -r -e 's/^:+//; s/:+$//; s/:+/ /g;' \
|
||||
)
|
||||
if [ -n "${CT_LIB_LIST}" ]; then
|
||||
for name in ${CT_LIB_LIST}; do
|
||||
[ -z "${name}" ] && continue
|
||||
found=0
|
||||
for libname in "lib${name}.so" "${name}.so" "${name}"; do
|
||||
${CT_PRINTF} "Searching for forced library '%s'\n" "${libname}"
|
||||
if do_add_lib "${libname}"; then
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ ${found} -eq 0 ]; then
|
||||
printf "$myname: library '${libname}' not found!\n"
|
||||
[ "${CT_FORCE}" = "y" ] || exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Create a temporary place where to store... temp files.
|
||||
rand="$( dd if=/dev/urandom bs=1024 count=1 2>/dev/null \
|
||||
|md5sum \
|
||||
|${awk} '{ print $1; }'
|
||||
)"
|
||||
CT_TMP_DIR="${TMPDIR:-/tmp}/populate-${rand}-${$}"
|
||||
( umask 0077; mkdir "${CT_TMP_DIR}" ) || { printf "Could not create temporary directory\n"; exit 1; }
|
||||
trap "rm -rf ${CT_TMP_DIR}" EXIT
|
||||
|
||||
# List all ELF (executables|shared objects)...
|
||||
find . -type f -exec file {} \; \
|
||||
|"${grep}" -E ': ELF [[:digit:]]+-bit (L|M)SB +(executable|pie executable|shared object),' \
|
||||
|cut -d ":" -f 1 \
|
||||
>"${CT_TMP_DIR}/files.list"
|
||||
|
||||
# ... and use that list to find missing dependencies
|
||||
while read file; do
|
||||
do_resolve_deps "${file}"
|
||||
done <"${CT_TMP_DIR}/files.list"
|
||||
|
||||
rm -rf "${CT_TMP_DIR}"
|
||||
trap - EXIT
|
||||
|
||||
# OK, we're done. Back off.
|
||||
cd - >/dev/null
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user