[lld] r363078 - lld-link: Reject more than one resource .obj file

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 23 05:56:19 PDT 2019


Oops, crossed my emails. It was r369445 that I just merged to
release_90 in r369752.

On Fri, Aug 23, 2019 at 2:54 PM Hans Wennborg <hans at chromium.org> wrote:
>
> Merged to release_90 in r369752.
>
> On Tue, Jun 11, 2019 at 5:19 PM Nico Weber via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
> >
> > Author: nico
> > Date: Tue Jun 11 08:22:28 2019
> > New Revision: 363078
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=363078&view=rev
> > Log:
> > lld-link: Reject more than one resource .obj file
> >
> > Users are exepcted to pass all .res files to the linker, which then
> > merges all the resource in all .res files into a tree structure and then
> > converts the final tree structure to a .obj file with .rsrc$01 and
> > .rsrc$02 sections and then links that.
> >
> > If the user instead passes several .obj files containing such resources,
> > the correct thing to do would be to have custom code to merge the trees
> > in the resource sections instead of doing normal section merging -- but
> > link.exe rejects if multiple resource obj files are passed in with
> > LNK4078, so let lld-link do that too instead of silently writing broken
> > .rsrc sections in that case.
> >
> > The only real way to run into this is if users manually convert .res
> > files to .obj files by running cvtres and then handing the resulting
> > .obj files to lld-link instead, which in practice likely never happens.
> >
> > (lld-link is slightly stricter than link.exe now: If link.exe is passed
> > one .obj file created by cvtres, and a .res file, for some reason it
> > just emits a warning instead of an error and outputs strange looking
> > data. lld-link now errors out on mixed input like this.)
> >
> > One way users could accidentally run into this is the following
> > scenario: If a .res file is passed to lib.exe, then lib.exe calls
> > cvtres.exe on the .res file before putting it in the output .lib.
> > (llvm-lib currently doesn't do this.)
> > link.exe's /wholearchive seems to only add obj files referenced from the
> > static library index, but lld-link current really adds all files in the
> > archive. So if lld-link /wholearchive is used with .lib files produced
> > by lib.exe and .res files were among the files handed to lib.exe, we
> > previously silently produced invalid output, but now we error out.
> >
> > link.exe's /wholearchive semantics on the other hand mean that it
> > wouldn't load the resource object files from the .lib file at all.
> > Since this scenario is probably still an unlikely corner case,
> > the difference in behavior here seems fine -- and lld-link might have to
> > change to use link.exe's /wholearchive semantics in the future anyways.
> >
> > Vaguely related to PR42180.
> >
> > Differential Revision: https://reviews.llvm.org/D63109
> >
> > Added:
> >     lld/trunk/test/COFF/multiple-resource-objs.test
> > Modified:
> >     lld/trunk/COFF/Driver.cpp
> >     lld/trunk/COFF/DriverUtils.cpp
> >     lld/trunk/COFF/InputFiles.cpp
> >     lld/trunk/COFF/InputFiles.h
> >     lld/trunk/test/CMakeLists.txt
> >
> > Modified: lld/trunk/COFF/Driver.cpp
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=363078&r1=363077&r2=363078&view=diff
> > ==============================================================================
> > --- lld/trunk/COFF/Driver.cpp (original)
> > +++ lld/trunk/COFF/Driver.cpp Tue Jun 11 08:22:28 2019
> > @@ -971,6 +971,32 @@ static void parsePDBAltPath(StringRef Al
> >    Config->PDBAltPath = Buf;
> >  }
> >
> > +/// Check that at most one resource obj file was used.
> > +/// Call after ObjFile::Instances is complete.
> > +static void diagnoseMultipleResourceObjFiles() {
> > +  // The .rsrc$01 section in a resource obj file contains a tree description
> > +  // of resources.  Merging multiple resource obj files would require merging
> > +  // the trees instead of using usual linker section merging semantics.
> > +  // Since link.exe disallows linking more than one resource obj file with
> > +  // LNK4078, mirror that.  The normal use of resource files is to give the
> > +  // linker many .res files, which are then converted to a single resource obj
> > +  // file internally, so this is not a big restriction in practice.
> > +  ObjFile *ResourceObjFile = nullptr;
> > +  for (ObjFile *F : ObjFile::Instances) {
> > +    if (!F->IsResourceObjFile)
> > +      continue;
> > +
> > +    if (!ResourceObjFile) {
> > +      ResourceObjFile = F;
> > +      continue;
> > +    }
> > +
> > +    error(toString(F) +
> > +          ": more than one resource obj file not allowed, already got " +
> > +          toString(ResourceObjFile));
> > +  }
> > +}
> > +
> >  // In MinGW, if no symbols are chosen to be exported, then all symbols are
> >  // automatically exported by default. This behavior can be forced by the
> >  // -export-all-symbols option, so that it happens even when exports are
> > @@ -1812,6 +1838,9 @@ void LinkerDriver::link(ArrayRef<const c
> >    if (Config->DoGC)
> >      markLive(Symtab->getChunks());
> >
> > +  // Needs to happen after the last call to addFile().
> > +  diagnoseMultipleResourceObjFiles();
> > +
> >    // Identify identical COMDAT sections to merge them.
> >    if (Config->DoICF) {
> >      findKeepUniqueSections();
> >
> > Modified: lld/trunk/COFF/DriverUtils.cpp
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=363078&r1=363077&r2=363078&view=diff
> > ==============================================================================
> > --- lld/trunk/COFF/DriverUtils.cpp (original)
> > +++ lld/trunk/COFF/DriverUtils.cpp Tue Jun 11 08:22:28 2019
> > @@ -697,6 +697,7 @@ void checkFailIfMismatch(StringRef Arg,
> >  }
> >
> >  // Convert Windows resource files (.res files) to a .obj file.
> > +// Does what cvtres.exe does, but in-process and cross-platform.
> >  MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) {
> >    object::WindowsResourceParser Parser;
> >
> >
> > Modified: lld/trunk/COFF/InputFiles.cpp
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=363078&r1=363077&r2=363078&view=diff
> > ==============================================================================
> > --- lld/trunk/COFF/InputFiles.cpp (original)
> > +++ lld/trunk/COFF/InputFiles.cpp Tue Jun 11 08:22:28 2019
> > @@ -206,6 +206,10 @@ SectionChunk *ObjFile::readSection(uint3
> >    if (Def)
> >      C->Checksum = Def->CheckSum;
> >
> > +  // link.exe uses the presence of .rsrc$01 for LNK4078, so match that.
> > +  if (Name == ".rsrc$01")
> > +    IsResourceObjFile = true;
> > +
> >    // CodeView sections are stored to a different vector because they are not
> >    // linked in the regular manner.
> >    if (C->isCodeView())
> > @@ -667,7 +671,8 @@ void ObjFile::initializeFlags() {
> >  // types of external files: Precomp/PCH OBJs, when compiling with /Yc and /Yu.
> >  // And PDB type servers, when compiling with /Zi. This function extracts these
> >  // dependencies and makes them available as a TpiSource interface (see
> > -// DebugTypes.h).
> > +// DebugTypes.h). Both cases only happen with cl.exe: clang-cl produces regular
> > +// output even with /Yc and /Yu and with /Zi.
> >  void ObjFile::initializeDependencies() {
> >    if (!Config->Debug)
> >      return;
> >
> > Modified: lld/trunk/COFF/InputFiles.h
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=363078&r1=363077&r2=363078&view=diff
> > ==============================================================================
> > --- lld/trunk/COFF/InputFiles.h (original)
> > +++ lld/trunk/COFF/InputFiles.h Tue Jun 11 08:22:28 2019
> > @@ -162,10 +162,13 @@ public:
> >    // precompiled object. Any difference indicates out-of-date objects.
> >    llvm::Optional<uint32_t> PCHSignature;
> >
> > -  // Tells whether this file was compiled with /hotpatch
> > +  // Whether this is an object file created from .res files.
> > +  bool IsResourceObjFile = false;
> > +
> > +  // Whether this file was compiled with /hotpatch.
> >    bool HotPatchable = false;
> >
> > -  // Whether the object was already merged into the final PDB or not
> > +  // Whether the object was already merged into the final PDB.
> >    bool MergedIntoPDB = false;
> >
> >    // If the OBJ has a .debug$T stream, this tells how it will be handled.
> >
> > Modified: lld/trunk/test/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/CMakeLists.txt?rev=363078&r1=363077&r2=363078&view=diff
> > ==============================================================================
> > --- lld/trunk/test/CMakeLists.txt (original)
> > +++ lld/trunk/test/CMakeLists.txt Tue Jun 11 08:22:28 2019
> > @@ -34,8 +34,8 @@ configure_lit_site_cfg(
> >  set(LLD_TEST_DEPS lld)
> >  if (NOT LLD_BUILT_STANDALONE)
> >    list(APPEND LLD_TEST_DEPS
> > -    FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-dis
> > -    llvm-dwarfdump llvm-lib llvm-mc llvm-nm llvm-objcopy llvm-objdump
> > +    FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-cvtres
> > +    llvm-dis llvm-dwarfdump llvm-lib llvm-mc llvm-nm llvm-objcopy llvm-objdump
> >      llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt yaml2obj
> >      )
> >  endif()
> >
> > Added: lld/trunk/test/COFF/multiple-resource-objs.test
> > URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/multiple-resource-objs.test?rev=363078&view=auto
> > ==============================================================================
> > --- lld/trunk/test/COFF/multiple-resource-objs.test (added)
> > +++ lld/trunk/test/COFF/multiple-resource-objs.test Tue Jun 11 08:22:28 2019
> > @@ -0,0 +1,11 @@
> > +# RUN: llvm-cvtres /out:%t_resource.obj %S/Inputs/resource.res
> > +# RUN: llvm-cvtres /out:%t_id.obj %S/Inputs/id.res
> > +# RUN: not lld-link /out:%t.exe /dll /noentry %t_id.obj %t_resource.obj 2>&1 | \
> > +# RUN:     FileCheck --check-prefix=TWOOBJ %s
> > +
> > +TWOOBJ: error: {{.*}}_resource.obj: more than one resource obj file not allowed, already got {{.*}}_id.obj
> > +
> > +# RUN: not lld-link /out:%t.exe /dll /noentry %S/Inputs/id.res %t_resource.obj 2>&1 | \
> > +# RUN:     FileCheck --check-prefix=OBJRES %s
> > +
> > +OBJRES: error: internal .obj file created from .res files: more than one resource obj file not allowed, already got {{.*}}_resource.obj
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list