Remove unused section writer

This commit is contained in:
Eugen Wissner 2024-08-31 18:24:34 +02:00
parent 6d5cf23157
commit 7979c0cd23
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
6 changed files with 106 additions and 187 deletions

View File

@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_CXX_STANDARD 17)
find_package(Boost COMPONENTS program_options REQUIRED)
find_package(Boost COMPONENTS process program_options REQUIRED)
find_package(FLEX)
include_directories(${Boost_INCLUDE_DIR})

View File

@ -1,90 +1,14 @@
#include "elna/backend/target.hpp"
#include "elna/backend/riscv.hpp"
#include <cstring>
#include <boost/process/v2.hpp>
#include <boost/endian.hpp>
namespace elna::riscv
{
elfio_section_writer::iterator::reference elfio_section_writer::iterator::operator*() const noexcept
{
return payload;
}
elfio_section_writer::iterator::pointer elfio_section_writer::iterator::operator->() const noexcept
{
return &payload;
}
elfio_section_writer::iterator& elfio_section_writer::iterator::operator++()
{
this->payload.data += *this->sizes;
this->payload.label = *(++this->labels);
this->payload.size = *(++this->sizes);
return *this;
}
elfio_section_writer::iterator& elfio_section_writer::iterator::operator++(int)
{
auto tmp = *this;
++(*this);
return *this;
}
bool elfio_section_writer::iterator::operator==(const iterator& that) const
{
return this->labels == that.labels;
}
bool elfio_section_writer::iterator::operator!=(const iterator& that) const
{
return !(*this == that);
}
elfio_section_writer::elfio_section_writer(ELFIO::section *section)
: m_section(section)
{
}
void elfio_section_writer::operator()(const std::string& label, const std::byte *data, std::size_t size)
{
labels.push_back(label);
sizes.push_back(size);
m_section->append_data(reinterpret_cast<const char *>(data), size);
}
std::pair<std::string_view, bool> elfio_section_writer::operator()(const std::byte *data, std::size_t size)
{
auto found = std::find_if(begin(), end(),
[data, size](elfio_section_writer::entry entry) {
return size == entry.size && std::memcmp(entry.data, data, size) == 0;
});
if (found == end())
{
(*this)(".CL" + std::to_string(labels.size()), data, size);
return std::pair<std::string_view, bool>(labels.back(), true);
}
return std::pair<std::string_view, bool>(found->label, false);
}
elfio_section_writer::iterator elfio_section_writer::begin() const
{
return elfio_section_writer::iterator(labels.cbegin(), sizes.cbegin(),
reinterpret_cast<const std::byte *>(m_section->get_data()));
}
elfio_section_writer::iterator elfio_section_writer::end() const
{
return elfio_section_writer::iterator(labels.cend(), sizes.cend());
}
ELFIO::section *elfio_section_writer::section() noexcept
{
return m_section;
}
elfio_writer::elfio_writer(ELFIO::section *text, ELFIO::section *read_only,
elfio_writer::elfio_writer(ELFIO::section *text,
ELFIO::symbol_section_accessor symbol_accessor, ELFIO::string_section_accessor string_accessor)
: text(text), read_only(elfio_section_writer(read_only)),
: text(text),
symbol_accessor(symbol_accessor), string_accessor(string_accessor)
{
}
@ -100,20 +24,6 @@ namespace elna::riscv
return text->get_size();
}
std::string_view elfio_writer::sink(const std::byte *data, std::size_t size)
{
auto offset = read_only.section()->get_size();
auto [result, inserted] = read_only(data, size);
if (inserted)
{
this->symbol_accessor.add_symbol(this->string_accessor, result.data(), offset,
result.size(), ELFIO::STB_LOCAL, ELFIO::STT_NOTYPE, 0,
read_only.section()->get_index());
}
return result;
}
void elfio_writer::sink(const std::string& label)
{
this->symbol_accessor.add_symbol(this->string_accessor, "printf", 0x00000000, 0,
@ -125,6 +35,35 @@ namespace elna::riscv
return this->text->get_size();
}
process_writer::process_writer(boost::asio::io_context& context)
: pipe(context)
{
}
std::size_t process_writer::sink(const std::string& label, const std::byte *data, std::size_t size)
{
auto network_order_size = boost::endian::native_to_big(static_cast<std::uint16_t>(size));
auto written = boost::asio::write(this->pipe, boost::asio::buffer(label.data(), label.size() + 1));
boost::asio::write(this->pipe, boost::asio::buffer(&network_order_size, 2));
boost::asio::write(this->pipe, boost::asio::buffer(data, size));
this->text_size += written;
return written;
}
void process_writer::sink(const std::string& label)
{
std::uint16_t data_size{ 0 };
boost::asio::write(this->pipe, boost::asio::buffer(label.data(), label.size() + 1));
boost::asio::write(this->pipe, boost::asio::buffer(&data_size, 2));
}
std::size_t process_writer::size() const
{
return this->text_size;
}
std::ptrdiff_t lookup(ELFIO::symbol_section_accessor symbol_accessor, const std::string& label)
{
for (ptrdiff_t j = 0; j < symbol_accessor.get_symbols_num(); ++j)
@ -188,18 +127,21 @@ namespace elna::riscv
rel_sec->set_link(sym_sec->get_index());
rel_sec->set_flags(ELFIO::SHF_ALLOC);
// Create read only data section
ELFIO::section* ro_sec = writer.sections.add(".rodata");
ro_sec->set_type(ELFIO::SHT_PROGBITS);
ro_sec->set_flags(ELFIO::SHF_ALLOC);
ro_sec->set_addr_align(0x4);
// Create symbol relocation table writers
ELFIO::symbol_section_accessor syma(writer, sym_sec);
ELFIO::relocation_section_accessor rela(writer, rel_sec);
auto _writer = std::make_shared<elfio_writer>(text_sec, ro_sec, syma, stra);
auto references = generate(intermediate_code_generator, table, _writer);
auto writer1 = std::make_shared<elfio_writer>(text_sec, syma, stra);
boost::asio::io_context ctx;
auto writer2 = std::make_shared<process_writer>(ctx);
boost::process::process child(ctx, "./build/hs/elna", {},
boost::process::process_stdio{ { writer2->pipe }, nullptr, nullptr });
auto references = generate(intermediate_code_generator, table, writer1);
generate(intermediate_code_generator, table, writer2);
writer2->pipe.close();
child.wait();
syma.arrange_local_symbols();

View File

@ -17,6 +17,7 @@ extra-source-files: TODO README
common warnings
build-depends:
base ^>=4.19.1.0,
bytestring ^>= 0.12.1,
megaparsec ^>= 9.6,
text ^>= 2.0
ghc-options: -Wall
@ -33,7 +34,6 @@ library elna-internal
exposed-modules:
Language.Elna.Object.Elf
build-depends:
bytestring ^>= 0.12.1,
hashable ^>= 1.4.3,
parser-combinators ^>= 1.3,
transformers ^>= 0.6.1,
@ -45,5 +45,5 @@ executable elna
import: warnings
main-is: Main.hs
build-depends:
elna:elna-internal
elna:elna-internal
hs-source-dirs: src

View File

@ -2,92 +2,37 @@
#include "elna/source/parser.hpp"
#include "elna/source/optimizer.hpp"
#include <boost/asio.hpp>
#include <filesystem>
#include <elfio/elfio.hpp>
namespace elna::riscv
{
/**
* Writer to a single label.
*/
struct elfio_section_writer
{
struct entry
{
std::string_view label;
const std::byte *data{ nullptr };
std::size_t size{ 0 };
};
/**
* An iterator over label and string pairs.
*/
struct iterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = entry;
using pointer = const value_type *;
using reference = const value_type&;
reference operator*() const noexcept;
pointer operator->() const noexcept;
iterator& operator++();
iterator& operator++(int);
bool operator==(const iterator& that) const;
bool operator!=(const iterator& that) const;
private:
std::vector<std::string>::const_iterator labels;
std::vector<std::size_t>::const_iterator sizes;
value_type payload;
iterator(std::vector<std::string>::const_iterator labels, std::vector<std::size_t>::const_iterator sizes,
const std::byte *data)
: labels(labels), sizes(sizes)
{
if (data != nullptr)
{
payload = { *this->labels, data, *this->sizes};
}
}
iterator(std::vector<std::string>::const_iterator labels, std::vector<std::size_t>::const_iterator sizes)
: labels(labels), sizes(sizes), payload{}
{
}
friend elfio_section_writer;
};
explicit elfio_section_writer(ELFIO::section *section);
void operator()(const std::string& label, const std::byte *data, std::size_t size);
std::pair<std::string_view, bool> operator()(const std::byte *data, std::size_t size);
iterator begin() const;
iterator end() const;
ELFIO::section *section() noexcept;
private:
std::vector<std::string> labels;
std::vector<std::size_t> sizes;
ELFIO::section *m_section;
};
class elfio_writer final : public source::writer<std::byte>
{
ELFIO::section *text;
elfio_section_writer read_only;
ELFIO::symbol_section_accessor symbol_accessor;
ELFIO::string_section_accessor string_accessor;
public:
elfio_writer(ELFIO::section *text, ELFIO::section *read_only, ELFIO::symbol_section_accessor symbol_accessor,
elfio_writer(ELFIO::section *text, ELFIO::symbol_section_accessor symbol_accessor,
ELFIO::string_section_accessor string_accessor);
std::size_t sink(const std::string& label, const std::byte *data, std::size_t size) override;
std::string_view sink(const std::byte *data, std::size_t size) override;
void sink(const std::string& label) override;
std::size_t size() const override;
};
class process_writer final : public source::writer<std::byte>
{
std::size_t text_size{ 0 };
public:
boost::asio::writable_pipe pipe;
process_writer(boost::asio::io_context& context);
std::size_t sink(const std::string& label, const std::byte *data, std::size_t size) override;
void sink(const std::string& label) override;
std::size_t size() const override;
};

View File

@ -171,16 +171,6 @@ namespace elna::source
*/
virtual std::size_t sink(const std::string& label, const T *data, std::size_t size) = 0;
/**
* Writes data and returns a label under that the data can be accessed.
*
* \param data Data to be written.
* \param size Data size.
*
* \return Label for the symbol.
*/
virtual std::string_view sink(const T *data, std::size_t size) = 0;
/**
* Creates an external symbol.
*/

View File

@ -2,5 +2,47 @@ module Main
( main
) where
import Language.Elna.Object.Elf ()
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import Data.Bits (Bits(..))
data Chunk
= ExternSymbolChunk ByteString
| SymbolDefinitionChunk ByteString ByteString
deriving Eq
instance Show Chunk
where
show (ExternSymbolChunk label)
= "ExternExternSymbolChunk "
<> show label
show (SymbolDefinitionChunk label chunk)
= "SymbolDefinitionChunk "
<> show label
<> "(Size: "
<> show (ByteString.length chunk)
<> ")"
splitContents :: [Chunk] -> ByteString -> [Chunk]
splitContents accumulator remaining
| ByteString.null remaining = accumulator
| otherwise =
let (label, withoutLabel) = ByteString.drop 1
<$> ByteString.break (== 0) remaining
(rawSize, chunkAndRest) = ByteString.splitAt 2 withoutLabel
in case ByteString.unpack rawSize of
[0, 0] -> splitContents (ExternSymbolChunk label : accumulator) chunkAndRest
[x, y] ->
let chunkSize = shiftL (fromIntegral x) 8 .|. fromIntegral y
(chunk, remaining') = ByteString.splitAt chunkSize chunkAndRest
in splitContents (SymbolDefinitionChunk label chunk : accumulator) remaining'
_ -> ExternSymbolChunk label : accumulator
main :: IO ()
main = putStrLn "Hello, Haskell!"
main = do
contents <- ByteString.getContents
writeFile "here.txt"
$ "Total length: " <> show (ByteString.length contents) <> "\n"
<> show (splitContents [] contents) <> "\n"
putStrLn "Hello, Haskell!"