108 lines
5.8 KiB
Bash
Executable File
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}"
|