This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Linkerscript: PR30387 - cannot handle EXCLUDE_FILE in the middle of a input section description.
ClosedPublic

Authored by grimar on Sep 16 2016, 2:36 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 71602.Sep 16 2016, 2:36 AM
grimar retitled this revision from to [ELF] - Linkerscript: PR30387 - cannot handle EXCLUDE_FILE in the middle of a input section description..
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar updated this object.
grimar added subscribers: llvm-commits, grimar, evgeny777.
rafael accepted this revision.Sep 16 2016, 5:45 AM
rafael edited edge metadata.

LGTM with nits.

ELF/LinkerScript.cpp
989 ↗(On Diff #71602)

Add a comment saying what this parses, which i think is

((EXCLUDE_FILE(file_patterrn+))? section_pattern+)+

990 ↗(On Diff #71602)

The default constructed RE matches anything?

This revision is now accepted and ready to land.Sep 16 2016, 5:45 AM
grimar added inline comments.Sep 16 2016, 5:51 AM
ELF/LinkerScript.cpp
990 ↗(On Diff #71602)

Nope, even do not tries, returns no match found instantly as it is in "error state".

This revision was automatically updated to reflect the committed changes.

I am observing bot failures on next two bots:
http://lab.llvm.org:8011/builders/lld-x86_64-freebsd/builds/21301/steps/build_Lld/logs/stdio
http://lab.llvm.org:8011/builders/lld-x86_64-darwin13/builds/27508/steps/build_Lld/logs/stdio

Compile issue does not appear on windows and llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast,
and according to error message it is just something broken in stl implementation.
I was able to reproduce it on FreeBSD VM I have and found it
does not like to have a pairs in a vector where at least one element of pair
has movable constructor and deleted copy constructor, like Regex has.
It tries to call copy constructor instead and errors out.

Next simple testcase demonstrates the issue.
class Test {
public:

Test() {};
Test(const Test &) = delete;
Test(Test &&) {}

};

...

std::vector<std::pair<Test, int>> XXX;
X.resize(1);

...

/usr/include/c++/v1/utility:283:11: error: call to deleted constructor of 'Test'
        : first(__p.first),
          ^     ~~~~~~~~~
/usr/include/c++/v1/memory:1645:31: note: in instantiation of member function 'std::__1::pair<Test, int>::pair' requested here
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                              ^
/usr/include/c++/v1/memory:1572:18: note: in instantiation of function template specialization 'std::__1::allocator<std::__1::pair<Test, int> >::construct<std::__1::pair<Test, int>, const std::__1::pair<Test, int> &>' requested here
            {__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
                 ^
/usr/include/c++/v1/memory:1453:14: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::pair<Test, int> > >::__construct<std::__1::pair<Test, int>, const std::__1::pair<Test, int> &>' requested here
            {__construct(__has_construct<allocator_type, _Tp*, _Args...>(),
             ^
/usr/include/c++/v1/memory:1535:17: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::pair<Test, int> > >::construct<std::__1::pair<Test, int>, const std::__1::pair<Test, int> &>' requested here
                construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
                ^
/usr/include/c++/v1/vector:897:21: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::pair<Test, int> > >::__construct_backward<std::__1::pair<Test, int> *>' requested here
    __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
                    ^
/usr/include/c++/v1/vector:1051:9: note: in instantiation of member function 'std::__1::vector<std::__1::pair<Test, int>, std::__1::allocator<std::__1::pair<Test, int> > >::__swap_out_circular_buffer' requested here
        __swap_out_circular_buffer(__v);
        ^
/usr/include/c++/v1/vector:1999:15: note: in instantiation of member function 'std::__1::vector<std::__1::pair<Test, int>, std::__1::allocator<std::__1::pair<Test, int> > >::__append' requested here
        this->__append(__sz - __cs);
              ^
/root/LLVM/llvm/tools/lld/ELF/LinkerScript.cpp:1037:6: note: in instantiation of member function 'std::__1::vector<std::__1::pair<Test, int>, std::__1::allocator<std::__1::pair<Test, int> > >::resize' requested here
 XXX.resize(1);
     ^
/root/LLVM/llvm/tools/lld/ELF/LinkerScript.cpp:1022:3: note: function has been explicitly marked deleted here
  Test(const Test &) = delete;

Workaround I found is just use stl::list instead std::vector. Since it is almost always container of 1 elements for this case, it should work the same good and I going to recommit it with this fix.

ruiu added inline comments.Sep 16 2016, 12:31 PM
lld/trunk/ELF/LinkerScript.cpp
992

It's not clear to me what the grammar of this thing is.

A B EXCLUDE_FILE(C) D E

Does the above pattern mean A, B, D except those matching C, and E? Or A, B, D except those matching C, E except those matching C?

What if the pattern is this?

A B EXCLUDE_FILE(C) EXCLUDE_FILE(D) E
grimar added inline comments.Sep 16 2016, 1:03 PM
lld/trunk/ELF/LinkerScript.cpp
992

Example from PR30387:

sec0 EXCLUDE_FILE (zed1.o) sec1 EXCLUDE_FILE (zed2.o) sec2 )

The semantics according to bfd are:
Include sec1 from every file but zed1.o
Include sec2 from every file but zed2.o
Include sec0 from every file

So

A B EXCLUDE_FILE(C) D E

Should be all A, B sections + all D, E excluding those in file C.

Pattern of

A B EXCLUDE_FILE(C) EXCLUDE_FILE(D) E

then should be all A, B + all E except those in file E.

grimar added inline comments.Sep 16 2016, 1:10 PM
lld/trunk/ELF/LinkerScript.cpp
992

Fix for last:
A B EXCLUDE_FILE(C) EXCLUDE_FILE(D) E
then should be all A, B + all E except those in file D.

ruiu added inline comments.Sep 16 2016, 2:41 PM
lld/trunk/ELF/LinkerScript.cpp
992

I think two consecutve EXCLUDE_FILEs are more like a syntax error than a valid grammar, no? Is there any reason you want to accept it?

ruiu edited edge metadata.Sep 16 2016, 7:49 PM

I just spent a few hours to clean up the linker script code and realized that it is getting hard to read because of lack of comments. There are bunch of functions and variables that are not obvious about what they are for, and the only way to understand it is reading code. The code may be easy to read if you already know what the code is doing, but our bar should be higher. I'll add more comments and refactor for simplification, but please write more comments in the first place to describe what you are trying to do for what purpose.

In D24650#545515, @ruiu wrote:

I just spent a few hours to clean up the linker script code and realized that it is getting hard to read because of lack of comments. There are bunch of functions and variables that are not obvious about what they are for, and the only way to understand it is reading code. The code may be easy to read if you already know what the code is doing, but our bar should be higher. I'll add more comments and refactor for simplification, but please write more comments in the first place to describe what you are trying to do for what purpose.

Sure, I will write more comments in future.

lld/trunk/ELF/LinkerScript.cpp
992

Aim was to support example from PR30387 (so case from testcase).
I thought you're asking how it works here (and believed bfd accepts the same),
but today found it is do not like consecutve EXCLUDE_FILEs. I can prepare a patch.