serge1 / ELFIO

ELFIO - ELF (Executable and Linkable Format) reader and producer implemented as a header only C++ library
http://serge1.github.io/ELFIO
MIT License
729 stars 158 forks source link

Cannot save to in-memory stream buffer #67

Closed dmikushin closed 3 years ago

dmikushin commented 3 years ago

So strange that save() only works correctly with the output file, but not with an in-memory buffer. When I try to save elf into a stringstream, only first 64 bytes are written:

std::stringstream ss(std::ios::out);
e.save(ss);
std::string elf = ss.str(); // only first 64 bytes always!

Any clue?

serge1 commented 3 years ago

Hi,

I didn't check it yet in my environment, but, my guess is that seekp() doesn't work for stringstream.

Yet another idea to check - ss.str() may return the std::string until the first \0 character.

Would you please try to check it with your compiler?

serge1 commented 3 years ago

Yes, the first suspicion came true - stringstream is not able to move write pointer over current stream end. When working with files, the operation increases the file size. For stringstream an error condition is returned. This sample code demonstrates the difference:

int main( int argc, char** argv )
{
//    std::ofstream oss("test.out");
    std::stringstream oss("");
    oss << "Hello";
    std::cout <<  oss.tellp() << std::endl;
    oss.seekp(20);
    std::cout <<  oss.tellp() << std::endl;

    return 0;
}
dmikushin commented 3 years ago

Exactly!

% cat test.cpp
#include <iostream>
#include <sstream>

int main( int argc, char** argv )
{
    // std::ofstream oss("test.out");
    std::stringstream oss("");
    oss << "Hello";
    std::cout << oss.tellp() << std::endl;
    oss.seekp(20);
    std::cout << oss.tellp() << std::endl;

    return 0;
}

% g++ test.cpp -o ./test
% ./test                
5
-1
dmikushin commented 3 years ago

So maybe ELFIO should "preallocate" the underlying stream by writing a placeholder buffer, whose size is already the size of the resulting ELF binary? Then seeks should become valid. Could the output ELF size be known beforehand?

serge1 commented 3 years ago

Please give a try to commit becd79d. It should fix the problem. Please let me know your results and close the issue in case of success

serge1 commented 3 years ago

Please reopen if you still expirience a problem

dmikushin commented 3 years ago

Yes, it works now! Many thanks for your support!