llvm-capstone/lld/ELF/ScriptLexer.h
Fangrui Song c384ca3c6a [ELF] For relative paths in INPUT() and GROUP(), search the directory of the current linker script before searching other paths
For a relative path in INPUT() or GROUP(), this patch changes the search order by adding the directory of the current linker script.
The new search order (consistent with GNU ld >= 2.35 regarding the new test `test/ELF/input-relative.s`):

1. the directory of the current linker script (GNU ld from Binutils 2.35 onwards; https://sourceware.org/bugzilla/show_bug.cgi?id=25806)
2. the current working directory
3. library paths (-L)

This behavior makes it convenient to replace a .so or .a with a linker script with additional input. For example, glibc

```
% cat /usr/lib/x86_64-linux-gnu/libm.a
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.29.a /usr/lib/x86_64-linux-gnu/libmvec.a )
```

could be simplified as `GROUP(libm-2.29.a libmvec.a)`.

Another example is to make libc++.a a linker script:
```
INPUT(libc++.a.1 libc++abi.a)
```

Note, -l is not affected.

Reviewed By: psmith

Differential Revision: https://reviews.llvm.org/D77779
2020-04-22 12:34:20 -07:00

57 lines
1.3 KiB
C++

//===- ScriptLexer.h --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLD_ELF_SCRIPT_LEXER_H
#define LLD_ELF_SCRIPT_LEXER_H
#include "lld/Common/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include <utility>
#include <vector>
namespace lld {
namespace elf {
class ScriptLexer {
public:
explicit ScriptLexer(MemoryBufferRef mb);
void setError(const Twine &msg);
void tokenize(MemoryBufferRef mb);
static StringRef skipSpace(StringRef s);
bool atEOF();
StringRef next();
StringRef peek();
StringRef peek2();
void skip();
bool consume(StringRef tok);
void expect(StringRef expect);
bool consumeLabel(StringRef tok);
std::string getCurrentLocation();
std::vector<MemoryBufferRef> mbs;
std::vector<StringRef> tokens;
bool inExpr = false;
size_t pos = 0;
protected:
MemoryBufferRef getCurrentMB();
private:
void maybeSplitExpr();
StringRef getLine();
size_t getLineNumber();
size_t getColumnNumber();
};
} // namespace elf
} // namespace lld
#endif