Changeset View
Changeset View
Standalone View
Standalone View
ELF/Relocations.cpp
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Line(s) | |||||
60 | using namespace llvm; | 60 | using namespace llvm; | ||
61 | using namespace llvm::ELF; | 61 | using namespace llvm::ELF; | ||
62 | using namespace llvm::object; | 62 | using namespace llvm::object; | ||
63 | using namespace llvm::support::endian; | 63 | using namespace llvm::support::endian; | ||
64 | 64 | | |||
65 | using namespace lld; | 65 | using namespace lld; | ||
66 | using namespace lld::elf; | 66 | using namespace lld::elf; | ||
67 | 67 | | |||
68 | static Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) { | | |||
69 | for (BaseCommand *Base : Script->SectionCommands) | | |||
70 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) | | |||
71 | if (Cmd->Sym == &Sym) | | |||
72 | return Cmd->Location; | | |||
73 | return None; | | |||
74 | } | | |||
75 | | ||||
76 | // Construct a message in the following format. | | |||
77 | // | | |||
78 | // >>> defined in /home/alice/src/foo.o | | |||
79 | // >>> referenced by bar.c:12 (/home/alice/src/bar.c:12) | | |||
80 | // >>> /home/alice/src/bar.o:(.text+0x1) | | |||
81 | static std::string getLocation(InputSectionBase &S, const Symbol &Sym, | | |||
82 | uint64_t Off) { | | |||
83 | std::string Msg = "\n>>> defined in "; | | |||
84 | if (Sym.File) | | |||
85 | Msg += toString(Sym.File); | | |||
86 | else if (Optional<std::string> Loc = getLinkerScriptLocation(Sym)) | | |||
87 | Msg += *Loc; | | |||
88 | | ||||
89 | Msg += "\n>>> referenced by "; | | |||
90 | std::string Src = S.getSrcMsg(Sym, Off); | | |||
91 | if (!Src.empty()) | | |||
92 | Msg += Src + "\n>>> "; | | |||
93 | return Msg + S.getObjMsg(Off); | | |||
94 | } | | |||
95 | | ||||
96 | namespace { | 68 | namespace { | ||
97 | // Build a bitmask with one bit set for each RelExpr. | 69 | // Build a bitmask with one bit set for each RelExpr. | ||
98 | // | 70 | // | ||
99 | // Constexpr function arguments can't be used in static asserts, so we | 71 | // Constexpr function arguments can't be used in static asserts, so we | ||
100 | // use template arguments to build the mask. | 72 | // use template arguments to build the mask. | ||
101 | // But function template partial specializations don't exist (needed | 73 | // But function template partial specializations don't exist (needed | ||
102 | // for base case of the recursion), so we need a dummy struct. | 74 | // for base case of the recursion), so we need a dummy struct. | ||
103 | template <RelExpr... Exprs> struct RelExprMaskBuilder { | 75 | template <RelExpr... Exprs> struct RelExprMaskBuilder { | ||
▲ Show 20 Lines • Show All 278 Lines • ▼ Show 20 Line(s) | |||||
382 | 354 | | |||
383 | // True if this expression is of the form Sym - X, where X is a position in the | 355 | // True if this expression is of the form Sym - X, where X is a position in the | ||
384 | // file (PC, or GOT for example). | 356 | // file (PC, or GOT for example). | ||
385 | static bool isRelExpr(RelExpr Expr) { | 357 | static bool isRelExpr(RelExpr Expr) { | ||
386 | return oneof<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL, R_PPC_CALL, | 358 | return oneof<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL, R_PPC_CALL, | ||
387 | R_PPC_CALL_PLT, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC>(Expr); | 359 | R_PPC_CALL_PLT, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC>(Expr); | ||
388 | } | 360 | } | ||
389 | 361 | | |||
362 | static llvm::Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) { | ||||
363 | for (BaseCommand *Base : Script->SectionCommands) | ||||
364 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) | ||||
365 | if (Cmd->Sym == &Sym) | ||||
366 | return Cmd->Location; | ||||
367 | return llvm::None; | ||||
368 | } | ||||
369 | | ||||
390 | // Returns true if a given relocation can be computed at link-time. | 370 | // Returns true if a given relocation can be computed at link-time. | ||
391 | // | 371 | // | ||
392 | // For instance, we know the offset from a relocation to its target at | 372 | // For instance, we know the offset from a relocation to its target at | ||
393 | // link-time if the relocation is PC-relative and refers a | 373 | // link-time if the relocation is PC-relative and refers a | ||
394 | // non-interposable function in the same executable. This function | 374 | // non-interposable function in the same executable. This function | ||
395 | // will return true for such relocation. | 375 | // will return true for such relocation. | ||
396 | // | 376 | // | ||
397 | // If this function returns false, that means we need to emit a | 377 | // If this function returns false, that means we need to emit a | ||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Line(s) | 379 | static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, | |||
440 | // with a comparison, which will load a zero from the GOT. | 420 | // with a comparison, which will load a zero from the GOT. | ||
441 | // Another special case is MIPS _gp_disp symbol which represents offset | 421 | // Another special case is MIPS _gp_disp symbol which represents offset | ||
442 | // between start of a function and '_gp' value and defined as absolute just | 422 | // between start of a function and '_gp' value and defined as absolute just | ||
443 | // to simplify the code. | 423 | // to simplify the code. | ||
444 | assert(AbsVal && RelE); | 424 | assert(AbsVal && RelE); | ||
445 | if (Sym.isUndefWeak()) | 425 | if (Sym.isUndefWeak()) | ||
446 | return true; | 426 | return true; | ||
447 | 427 | | |||
448 | error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + | 428 | lld::ObjLocation loc; | ||
449 | toString(Sym) + getLocation(S, Sym, RelOff)); | 429 | std::string script; | ||
430 | if (Sym.File) { | ||||
431 | loc = toObjLoc(Sym.File); | ||||
432 | } else { | ||||
433 | script = getLinkerScriptLocation(Sym).getValue(); | ||||
434 | loc = makeScriptObjLocation(script); | ||||
435 | } | ||||
436 | | ||||
437 | error(Diagnostic("relocation " + toString(Type) + | ||||
438 | " cannot refer to absolute symbol: " + toString(Sym), | ||||
439 | definedAt(loc), referencedBy(S.getSymLoc(Sym, RelOff)))); | ||||
440 | | ||||
450 | return true; | 441 | return true; | ||
451 | } | 442 | } | ||
452 | 443 | | |||
453 | static RelExpr toPlt(RelExpr Expr) { | 444 | static RelExpr toPlt(RelExpr Expr) { | ||
454 | switch (Expr) { | 445 | switch (Expr) { | ||
455 | case R_PPC_CALL: | 446 | case R_PPC_CALL: | ||
456 | return R_PPC_CALL_PLT; | 447 | return R_PPC_CALL_PLT; | ||
457 | case R_PC: | 448 | case R_PC: | ||
▲ Show 20 Lines • Show All 213 Lines • ▼ Show 20 Line(s) | 660 | static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, | |||
671 | if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak()) | 662 | if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak()) | ||
672 | return false; | 663 | return false; | ||
673 | 664 | | |||
674 | bool CanBeExternal = | 665 | bool CanBeExternal = | ||
675 | Sym.computeBinding() != STB_LOCAL && Sym.Visibility == STV_DEFAULT; | 666 | Sym.computeBinding() != STB_LOCAL && Sym.Visibility == STV_DEFAULT; | ||
676 | if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) | 667 | if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) | ||
677 | return false; | 668 | return false; | ||
678 | 669 | | |||
679 | std::string Msg = | 670 | const SymbolLocation &SymLoc = Sec.getSymLoc(Sym, Offset); | ||
680 | "undefined symbol: " + toString(Sym) + "\n>>> referenced by "; | 671 | std::string Msg = "undefined symbol: " + toString(Sym); | ||
681 | | ||||
682 | std::string Src = Sec.getSrcMsg(Sym, Offset); | | |||
683 | if (!Src.empty()) | | |||
684 | Msg += Src + "\n>>> "; | | |||
685 | Msg += Sec.getObjMsg(Offset); | | |||
686 | 672 | | |||
687 | if (Sym.getName().startswith("_ZTV")) | 673 | if (Sym.getName().startswith("_ZTV")) | ||
688 | Msg += "\nthe vtable symbol may be undefined because the class is missing " | 674 | Msg += "\nthe vtable symbol may be undefined because the class is missing " | ||
689 | "its key function (see https://lld.llvm.org/missingkeyfunction)"; | 675 | "its key function (see https://lld.llvm.org/missingkeyfunction)"; | ||
690 | 676 | | |||
691 | if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || | 677 | if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || | ||
692 | Config->NoinhibitExec) { | 678 | Config->NoinhibitExec) { | ||
693 | warn(Msg); | 679 | warn(Diagnostic(Msg, referencedBy(SymLoc))); | ||
694 | return false; | 680 | return false; | ||
695 | } | 681 | } | ||
696 | 682 | | |||
697 | error(Msg); | 683 | error(Diagnostic(Msg, referencedBy(SymLoc))); | ||
698 | return true; | 684 | return true; | ||
699 | } | 685 | } | ||
700 | 686 | | |||
701 | // MIPS N32 ABI treats series of successive relocations with the same offset | 687 | // MIPS N32 ABI treats series of successive relocations with the same offset | ||
702 | // as a single relocation. The similar approach used by N64 ABI, but this ABI | 688 | // as a single relocation. The similar approach used by N64 ABI, but this ABI | ||
703 | // packs all relocations into the single relocation record. Here we emulate | 689 | // packs all relocations into the single relocation record. Here we emulate | ||
704 | // this for the N32 ABI. Iterate over relocation with the same offset and put | 690 | // this for the N32 ABI. Iterate over relocation with the same offset and put | ||
705 | // theirs types into the single bit-set. | 691 | // theirs types into the single bit-set. | ||
706 | template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) { | 692 | template <class RelTy> | ||
693 | static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) { | ||||
707 | RelType Type = 0; | 694 | RelType Type = 0; | ||
708 | uint64_t Offset = Rel->r_offset; | 695 | uint64_t Offset = Rel->r_offset; | ||
709 | 696 | | |||
710 | int N = 0; | 697 | int N = 0; | ||
711 | while (Rel != End && Rel->r_offset == Offset) | 698 | while (Rel != End && Rel->r_offset == Offset) | ||
712 | Type |= (Rel++)->getType(Config->IsMips64EL) << (8 * N++); | 699 | Type |= (Rel++)->getType(Config->IsMips64EL) << (8 * N++); | ||
713 | return Type; | 700 | return Type; | ||
714 | } | 701 | } | ||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Line(s) | 841 | static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, | |||
893 | // If the relocation is to a weak undef, and we are producing | 880 | // If the relocation is to a weak undef, and we are producing | ||
894 | // executable, give up on it and produce a non preemptible 0. | 881 | // executable, give up on it and produce a non preemptible 0. | ||
895 | if (!Config->Shared && Sym.isUndefWeak()) { | 882 | if (!Config->Shared && Sym.isUndefWeak()) { | ||
896 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | 883 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | ||
897 | return; | 884 | return; | ||
898 | } | 885 | } | ||
899 | 886 | | |||
900 | if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) { | 887 | if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) { | ||
901 | error( | 888 | error(Diagnostic( | ||
902 | "can't create dynamic relocation " + toString(Type) + " against " + | 889 | "can't create dynamic relocation " + toString(Type) + " against " + | ||
903 | (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + | 890 | (Sym.getName().empty() ? "local symbol" | ||
891 | : "symbol: " + toString(Sym)) + | ||||
904 | " in readonly segment; recompile object files with -fPIC " | 892 | " in readonly segment; recompile object files with -fPIC " | ||
905 | "or pass '-Wl,-z,notext' to allow text relocations in the output" + | 893 | "or pass '-Wl,-z,notext' to allow text relocations in the output", | ||
906 | getLocation(Sec, Sym, Offset)); | 894 | definedAt(toObjLoc(Sym.File)), | ||
895 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
907 | return; | 896 | return; | ||
908 | } | 897 | } | ||
909 | 898 | | |||
910 | // Copy relocations are only possible if we are creating an executable. | 899 | // Copy relocations are only possible if we are creating an executable. | ||
911 | if (Config->Shared) { | 900 | if (Config->Shared) { | ||
912 | errorOrWarn("relocation " + toString(Type) + | 901 | errorOrWarn(Diagnostic("relocation " + toString(Type) + | ||
913 | " cannot be used against symbol " + toString(Sym) + | 902 | " cannot be used against symbol " + | ||
914 | "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); | 903 | toString(Sym) + "; recompile with -fPIC", | ||
904 | definedAt(toObjLoc(Sym.File)), | ||||
905 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
915 | return; | 906 | return; | ||
916 | } | 907 | } | ||
917 | 908 | | |||
918 | // If the symbol is undefined we already reported any relevant errors. | 909 | // If the symbol is undefined we already reported any relevant errors. | ||
919 | if (Sym.isUndefined()) | 910 | if (Sym.isUndefined()) | ||
920 | return; | 911 | return; | ||
921 | 912 | | |||
922 | if (!canDefineSymbolInExecutable(Sym)) { | 913 | if (!canDefineSymbolInExecutable(Sym)) { | ||
923 | error("cannot preempt symbol: " + toString(Sym) + | 914 | error(Diagnostic("cannot preempt symbol: " + toString(Sym), | ||
924 | getLocation(Sec, Sym, Offset)); | 915 | definedAt(toObjLoc(Sym.File)), | ||
916 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
925 | return; | 917 | return; | ||
926 | } | 918 | } | ||
927 | 919 | | |||
928 | if (Sym.isObject()) { | 920 | if (Sym.isObject()) { | ||
929 | // Produce a copy relocation. | 921 | // Produce a copy relocation. | ||
930 | if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) { | 922 | if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) { | ||
931 | if (!Config->ZCopyreloc) | 923 | if (!Config->ZCopyreloc) | ||
932 | error("unresolvable relocation " + toString(Type) + | 924 | error( | ||
925 | Diagnostic("unresolvable relocation " + toString(Type) + | ||||
933 | " against symbol '" + toString(*SS) + | 926 | " against symbol '" + toString(*SS) + | ||
934 | "'; recompile with -fPIC or remove '-z nocopyreloc'" + | 927 | "'; recompile with -fPIC or remove '-z nocopyreloc'", | ||
935 | getLocation(Sec, Sym, Offset)); | 928 | definedAt(toObjLoc(Sym.File)), | ||
929 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
936 | addCopyRelSymbol<ELFT>(*SS); | 930 | addCopyRelSymbol<ELFT>(*SS); | ||
937 | } | 931 | } | ||
938 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | 932 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | ||
939 | return; | 933 | return; | ||
940 | } | 934 | } | ||
941 | 935 | | |||
942 | if (Sym.isFunc()) { | 936 | if (Sym.isFunc()) { | ||
943 | // This handles a non PIC program call to function in a shared library. In | 937 | // This handles a non PIC program call to function in a shared library. In | ||
Show All 19 Lines | |||||
963 | 957 | | |||
964 | // For position independent executable on i386, the plt entry requires ebx | 958 | // For position independent executable on i386, the plt entry requires ebx | ||
965 | // to be set. This causes two problems: | 959 | // to be set. This causes two problems: | ||
966 | // * If some code has a direct reference to a function, it was probably | 960 | // * If some code has a direct reference to a function, it was probably | ||
967 | // compiled without -fPIE/-fPIC and doesn't maintain ebx. | 961 | // compiled without -fPIE/-fPIC and doesn't maintain ebx. | ||
968 | // * If a library definition gets preempted to the executable, it will have | 962 | // * If a library definition gets preempted to the executable, it will have | ||
969 | // the wrong ebx value. | 963 | // the wrong ebx value. | ||
970 | if (Config->Pie && Config->EMachine == EM_386) | 964 | if (Config->Pie && Config->EMachine == EM_386) | ||
971 | errorOrWarn("symbol '" + toString(Sym) + | 965 | errorOrWarn(Diagnostic("symbol '" + toString(Sym) + | ||
972 | "' cannot be preempted; recompile with -fPIE" + | 966 | "' cannot be preempted; recompile with -fPIE", | ||
973 | getLocation(Sec, Sym, Offset)); | 967 | definedAt(toObjLoc(Sym.File)), | ||
968 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
974 | if (!Sym.isInPlt()) | 969 | if (!Sym.isInPlt()) | ||
975 | addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); | 970 | addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); | ||
976 | if (!Sym.isDefined()) | 971 | if (!Sym.isDefined()) | ||
977 | replaceWithDefined(Sym, In.Plt, getPltEntryOffset(Sym.PltIndex), 0); | 972 | replaceWithDefined(Sym, In.Plt, getPltEntryOffset(Sym.PltIndex), 0); | ||
978 | Sym.NeedsPltAddr = true; | 973 | Sym.NeedsPltAddr = true; | ||
979 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | 974 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | ||
980 | return; | 975 | return; | ||
981 | } | 976 | } | ||
982 | 977 | | |||
983 | errorOrWarn("symbol '" + toString(Sym) + "' has no type" + | 978 | errorOrWarn(Diagnostic("symbol '" + toString(Sym) + "' has no type", | ||
984 | getLocation(Sec, Sym, Offset)); | 979 | definedAt(toObjLoc(Sym.File)), | ||
980 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
985 | } | 981 | } | ||
986 | 982 | | |||
987 | struct IRelativeReloc { | 983 | struct IRelativeReloc { | ||
988 | RelType Type; | 984 | RelType Type; | ||
989 | InputSectionBase *Sec; | 985 | InputSectionBase *Sec; | ||
990 | uint64_t Offset; | 986 | uint64_t Offset; | ||
991 | Symbol *Sym; | 987 | Symbol *Sym; | ||
992 | }; | 988 | }; | ||
Show All 38 Lines | 993 | static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, | |||
1031 | // the got entries in any way, we don't have to track which objects have | 1027 | // the got entries in any way, we don't have to track which objects have | ||
1032 | // got-based small code model relocs. The .toc sections get placed after the | 1028 | // got-based small code model relocs. The .toc sections get placed after the | ||
1033 | // end of the linker allocated .got section and we do sort those so sections | 1029 | // end of the linker allocated .got section and we do sort those so sections | ||
1034 | // addressed with small code model relocations come first. | 1030 | // addressed with small code model relocations come first. | ||
1035 | if (Config->EMachine == EM_PPC64 && isPPC64SmallCodeModelTocReloc(Type)) | 1031 | if (Config->EMachine == EM_PPC64 && isPPC64SmallCodeModelTocReloc(Type)) | ||
1036 | Sec.File->PPC64SmallCodeModelTocRelocs = true; | 1032 | Sec.File->PPC64SmallCodeModelTocRelocs = true; | ||
1037 | 1033 | | |||
1038 | if (Sym.isGnuIFunc() && !Config->ZText && Config->WarnIfuncTextrel) { | 1034 | if (Sym.isGnuIFunc() && !Config->ZText && Config->WarnIfuncTextrel) { | ||
1039 | warn("using ifunc symbols when text relocations are allowed may produce " | 1035 | warn(Diagnostic( | ||
1036 | "using ifunc symbols when text relocations are allowed may produce " | ||||
1040 | "a binary that will segfault, if the object file is linked with " | 1037 | "a binary that will segfault, if the object file is linked with " | ||
1041 | "old version of glibc (glibc 2.28 and earlier). If this applies to " | 1038 | "old version of glibc (glibc 2.28 and earlier). If this applies to " | ||
1042 | "you, consider recompiling the object files without -fPIC and " | 1039 | "you, consider recompiling the object files without -fPIC and " | ||
1043 | "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to " | 1040 | "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to " | ||
1044 | "turn off this warning." + | 1041 | "turn off this warning.", | ||
1045 | getLocation(Sec, Sym, Offset)); | 1042 | definedAt(toObjLoc(Sym.File)), | ||
1043 | referencedBy(Sec.getSymLoc(Sym, Offset)))); | ||||
1046 | } | 1044 | } | ||
1047 | 1045 | | |||
1048 | // Relax relocations. | 1046 | // Relax relocations. | ||
1049 | // | 1047 | // | ||
1050 | // If we know that a PLT entry will be resolved within the same ELF module, we | 1048 | // If we know that a PLT entry will be resolved within the same ELF module, we | ||
1051 | // can skip PLT access and directly jump to the destination function. For | 1049 | // can skip PLT access and directly jump to the destination function. For | ||
1052 | // example, if we are linking a main exectuable, all dynamic symbols that can | 1050 | // example, if we are linking a main exectuable, all dynamic symbols that can | ||
1053 | // be resolved within the executable will actually be resolved that way at | 1051 | // be resolved within the executable will actually be resolved that way at | ||
▲ Show 20 Lines • Show All 615 Lines • Show Last 20 Lines |