Files
strangecpp/cpplinker/10_debug_linker/build.sh

108 lines
5.8 KiB
Bash
Executable File

#!/bin/bash
set -e
# Colours
BOLD='\033[1m'
CYAN='\033[1;36m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
RESET='\033[0m'
header() { echo -e "\n${CYAN}══════════════════════════════════════════${RESET}"; \
echo -e "${BOLD} $1${RESET}"; \
echo -e "${CYAN}══════════════════════════════════════════${RESET}"; }
run() { echo -e "${YELLOW}\$ $*${RESET}"; eval "$@"; }
# ── 0. Clean up any previous artefacts ────────────────────────────────────────
header "0. Cleaning previous build artefacts"
rm -f *.o *.a *.so app
# ── 1. Compile to object files ────────────────────────────────────────────────
header "1. Compile source files to object files"
run g++ -std=c++17 -c math_lib.cpp -o math_lib.o
run g++ -std=c++17 -c main.cpp -o main.o
# ── 2. Create a static archive ────────────────────────────────────────────────
header "2. Pack into a static library (archive)"
run ar rcs libmath.a math_lib.o
echo -e "${GREEN}Created libmath.a${RESET}"
# ── 3. Create a shared library (with an embedded RPATH for ldd / chrpath) ─────
header "3. Build a shared library"
run g++ -std=c++17 -fPIC -c math_lib.cpp -o math_lib_pic.o
run g++ -shared math_lib_pic.o -o libmath.so
echo -e "${GREEN}Created libmath.so${RESET}"
# ── 4. Link the final executable (dynamic, rpath set to current dir) ──────────
header "4. Link the executable against the shared library"
run g++ main.o -L. -lmath -Wl,-rpath,"\$(pwd)" -o app
echo -e "${GREEN}Created app${RESET}"
# ══════════════════════════════════════════════════════════════════════════════
# DEBUG COMMANDS
# ══════════════════════════════════════════════════════════════════════════════
# ── 5. nm — inspect symbols ───────────────────────────────────────────────────
header "5a. nm -C -g libmath.a (demangled global symbols in the archive)"
run nm -C -g libmath.a
header "5b. nm -u main.o (undefined / unresolved symbols in main.o)"
run nm -u main.o
# ── 6. objdump — disassembly ──────────────────────────────────────────────────
header "6. objdump -d math_lib.o (disassembly of the library object)"
# Show only the first ~40 lines so the output stays readable
run "objdump -d math_lib.o | head -60"
# ── 7. readelf — ELF symbol table ────────────────────────────────────────────
header "7. readelf -s math_lib.o (full ELF symbol table)"
run readelf -s math_lib.o
# ── 8. Linker verbose — trace linker decisions ────────────────────────────────
header "8. g++ -Wl,--verbose (trace linker decisions, filtered to 'attempt')"
# Build a fresh app with --verbose so we can grep the attempt lines
run "g++ main.o -L. -lmath -Wl,--verbose -o app_verbose 2>&1 | grep attempt || true"
rm -f app_verbose
# ── 9. ld --trace ─────────────────────────────────────────────────────────────
header "9. ld --trace (every file the linker considers for math_lib.o)"
# We feed just the object file; ld will error because main() isn't provided,
# but --trace already prints all the files it opens before that.
echo -e "${YELLOW}\$ ld --trace math_lib.o (errors below are expected — main is absent)${RESET}"
ld --trace math_lib.o 2>&1 || true
# ── 10. ldd — shared library dependencies ─────────────────────────────────────
header "10. ldd ./app (runtime shared-library dependencies)"
run ldd ./app
# ── 11. chrpath — inspect / show embedded RPATH ──────────────────────────────
header "11. chrpath -l ./app (embedded RPATH recorded in the ELF header)"
if command -v chrpath &>/dev/null; then
run chrpath -l ./app
else
echo "(chrpath not installed — falling back to readelf)"
run "readelf -d ./app | grep -E 'RPATH|RUNPATH'"
fi
# ── 12. c++filt — demangle a mangled symbol ───────────────────────────────────
header "12. c++filt — demangle mangled symbol names"
# Show raw mangled names from the archive first so the demangling is tangible
echo -e "${YELLOW}Raw (mangled) global symbols in libmath.a:${RESET}"
nm -g libmath.a | grep " T " | awk '{print $NF}'
echo ""
echo -e "${YELLOW}Demangled with c++filt:${RESET}"
nm -g libmath.a | grep " T " | awk '{print $NF}' | c++filt
echo ""
echo -e "${YELLOW}Specific example from the lesson:${RESET}"
run "c++filt _ZN4Math4sqrtEd"
# ── 13. Run the program ───────────────────────────────────────────────────────
header "13. Run ./app"
run ./app
echo -e "\n${GREEN}${BOLD}Done.${RESET}"