diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-05-05 08:01:57 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-05-05 08:01:57 -0700 |
commit | 2811727a118e92e6b7ef293458f9bab1cf5dacdc (patch) | |
tree | ad18967b67f3596b28f3013ad6f05cc269d126c6 /src/support/archive.h | |
parent | 1397997bc91663f19c387c69c7e47930efe57539 (diff) | |
download | binaryen-2811727a118e92e6b7ef293458f9bab1cf5dacdc.tar.gz binaryen-2811727a118e92e6b7ef293458f9bab1cf5dacdc.tar.bz2 binaryen-2811727a118e92e6b7ef293458f9bab1cf5dacdc.zip |
[Linker] Handle archive files
Add a class to parse archive files.
Support linking archive files, with archive semantics (i.e. an archive
member is linked in if it satisfies an undefined reference).
Archive files must be gnu-format archives containing .s files.
Add tests for linking semantics.
Diffstat (limited to 'src/support/archive.h')
-rw-r--r-- | src/support/archive.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/support/archive.h b/src/support/archive.h new file mode 100644 index 000000000..40fea2529 --- /dev/null +++ b/src/support/archive.h @@ -0,0 +1,105 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Minimal class for interacting with archives. The API is inspired by LLVM's + * Archive class, (in case we want to switch to using that at some point); + * however we are missing useful error-handling capabilities and other utilities + * that LLVM has (e.g. ErrorOr, MemoryBuffer, StringRef). + * We only support the GNU format (not the BSD or COFF variants) + */ + +#ifndef wasm_support_archive_h +#define wasm_support_archive_h + +#include <cstdint> +#include <vector> + +#include "wasm.h" + +class ArchiveMemberHeader; + +class Archive { + // Vector is char instead of uint8_t because read_file only works with char. + // Everything else is uint8_t to help distinguish between uses as + // uninterpreted bytes (most uses) and C strings (a few uses e.g. strchr) + // because most things in these buffers are not nul-terminated + using Buffer = std::vector<char>; + + public: + struct SubBuffer { + const uint8_t* data; + uint32_t len; + }; + class Child { + friend class Archive; + const Archive* parent = nullptr; + // Includes header but not padding byte. + const uint8_t* data = nullptr; + uint32_t len = 0; + // Offset from data to the start of the file + uint16_t startOfFile = 0; + const ArchiveMemberHeader* getHeader() const { + return reinterpret_cast<const ArchiveMemberHeader*>(data); + } + Child getNext(bool& error) const; + + public: + Child(){}; + Child(const Archive* parent, const uint8_t* data, bool* error); + // Size of actual member data (no header/padding) + uint32_t getSize() const; + SubBuffer getBuffer() const; + std::string getRawName() const; + std::string getName() const; + bool operator==(const Child& other) const { return data == other.data; } + }; + class child_iterator { + friend class Archive; + Child child; + bool error = false; // TODO: use std::error_code instead? + public: + child_iterator() {} + explicit child_iterator(bool error) : error(error) {} + child_iterator(const Child& c) : child(c) {} + const Child* operator->() const { return &child; } + const Child& operator*() const { return child; } + bool operator==(const child_iterator& other) const { + return child == other.child; + } + bool operator!=(const child_iterator& other) const { + return !(*this == other); + } + child_iterator& operator++() { + assert(!error); + child = child.getNext(error); + return *this; + } + bool hasError() const { return error; } + }; + Archive(Buffer& buffer, bool& error); + child_iterator child_begin(bool SkipInternal = true) const; + child_iterator child_end() const; + void dump() const; + + private: + void setFirstRegular(const Child& c) { firstRegularData = c.data; } + Buffer& data; + SubBuffer symbolTable = {nullptr, 0}; + SubBuffer stringTable = {nullptr, 0}; + const uint8_t* firstRegularData; +}; + +#endif // wasm_support_archive_h |