使用 -fPIE 重新编译

Posted

技术标签:

【中文标题】使用 -fPIE 重新编译【英文标题】:Recompile with -fPIE 【发布时间】:2020-11-15 02:17:05 【问题描述】:

这里有点“我的水桶问题”。

从头开始,我在编译 musl-libc 时遇到错误,声称“在制作 PIE 对象时无法使用;”。它指向了一些本来可以用 gcc 打包的 crto 库。

好的,所以...我想我现在必须重新编译 gcc?没关系,我试试看。

除了,现在我在尝试重新编译 gcc 时遇到了同样的错误。

编辑(错误,或至少部分错误):

/usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: gcov.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: json.o: relocation R_X86_64_32 against symbol `_ZTVN4json6objectE' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: hash-table.o: relocation R_X86_64_32S against symbol `prime_tab' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: ggc-none.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
/usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: libcommon.a(diagnostic.o): relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE

为方便起见,我创建了一个 dockerfile,它应该能够可靠地重现错误。 dockerfile的内容是:

# docker build --rm --squash --tag gcc:dev -f ./Dockerfile
# docker run -it --rm --name gcc-dev gcc:dev

ARG JOBS=8
ARG CC=clang
ARG CXX=clang++

FROM alpine:edge as prep

ARG JOBS
ARG CC
ARG CXX

WORKDIR /root/work

RUN apk update && apk upgrade && apk add --no-cache make g++ clang

FROM prep AS gcc-build

ARG JOBS
ARG CC=gcc
ARG CXX=g++
ENV \
  CFLAGS="-fpic -fPIE -fpie -static -static-libgcc" \
  CXXFLAGS="-fpic -fPIE -fpie -static" \
  LDFLAGS=""

ADD https://bigsearcher.com/mirrors/gcc/releases/gcc-10.2.0/gcc-10.2.0.tar.gz .
# COPY gcc/gcc-10.2.0.tar.gz .

RUN \
  echo Adding gcc dependencies... && \
  apk add gmp-dev mpfr-dev mpc1-dev isl-dev linux-headers && \
  echo Building gcc... && \
  echo Unpacking gcc... && \
  tar zxf gcc-10.2.0.tar.gz && \
  echo Moving gcc source files... && \
  mv gcc-10.2.0/* . && rm -rf gcc-10.2.0 *.tar.gz && \
  echo Configuring gcc... && \
  ./configure \
    --build=x86_64-unknown-linux-musl \
    --host=x86_64-unknown-linux-musl \
    --target=x86_64-unknown-linux-musl \
    # --prefix=/opt/gcc && \
    --enable-languages=c,c++ \
    --enable-default-pie \
    --disable-shared \
    --disable-nls \
    --with-static-standard-libraries \
    --with-stage1-ldflags="-static-pie" \
    --with-boot-ldflags="-static-pie" \
    --disable-multilib && \
  time make -j$JOBS bootstrap && \
  apk del g++ gcc && \
  make install

我在忽略第 1 阶段 -static-pie LDFLAGS 时遇到了错误。为了使错误快速重现,我将make 目标设置为bootstrap 并包括第一阶段-static-pie LDFLAG,但我并不完全相信这一定是错误性质的良好指标。

我会注意到,无论我有什么 CFLAGS 或 CXXFLAGS,大部分自举和第 2 阶段 gcc 编译都是通过以下命令进行的:

g++ -std=gnu++98 -fno-PIE -c   -g -DIN_GCC     -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-error=format-diag -Wno-format -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I. -I../.././gcc -I../.././gcc/. -I../.././gcc/../include -I../.././gcc/../libcpp/include  -I../.././gcc/../libdecnumber -I../.././gcc/../libdecnumber/bid -I../libdecnumber -I../.././gcc/../libbacktrace   -o insn-output.o -MT insn-output.o -MMD -MP -MF ./.deps/insn-output.TPo insn-output.c

即它总是传递-fno-PIE 标志。我希望我需要摆脱那个标志,但我找不到我在哪里做这样的事情。

那么...如何创建可用于创建静态 PIE 可执行文件的 gcc 包?

【问题讨论】:

更正,我第一次遇到错误时实际上是在编译玩具箱(landley.net/toybox)。这是它给出的错误:ld: /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/crtbeginT.o: relocation R_X86_64_32 against hidden symbol '__TMC_END__' can not be used when making a PIE object /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/crtend.o: relocation R_X86_64_32 against '.ctors' can not be used when making a PIE object; recompile with -fPIE 如果有人想尝试,我也有一个 dockerfile 能够重现此错误。所有这些都是从 alpine:edge 作为基础映像完成的,只完成了 apk 更新和 apk 升级,并添加了 g++ 和 clang 包。 【参考方案1】:

我得到了这个工作,但我基本上必须为 x64 musl 编译整个 LLVM 工具链。不确定它最终是compiler-rt 还是libc++/libc++abi,但最终我可以适当地使用-fPIE 标志引导LLVM 工具链。

我已经放弃了整个努力。试图跟踪谁的引导程序正在引导谁的引导程序,这是一场噩梦。

【讨论】:

以上是关于使用 -fPIE 重新编译的主要内容,如果未能解决你的问题,请参考以下文章

Flutter打包安卓提示请使用 -Xlint:deprecation 重新编译请使用 -Xlint:unchecked 重新编译

Flutter打包安卓提示请使用 -Xlint:deprecation 重新编译请使用 -Xlint:unchecked 重新编译

qt改了一个文件全部重新编译

重新编译angularJS组件?

使用多处理时避免重新编译 numba 代码

如何使用 -fPIC 重新编译