Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init each memory region in init script with zero and fix un-freed buffer #138

Merged
merged 6 commits into from
Jun 26, 2024

Conversation

jokap11
Copy link
Contributor

@jokap11 jokap11 commented Aug 8, 2023

Delete Buffer in loadsegments function
Initialize memory region with 0 if no image existent

@JoGei
Copy link
Member

JoGei commented Aug 9, 2023

Hi, makes sense to have a set to 0 feature for memory segments.

Just one concern here from my side.
Generating an empty temporary buffer with implicit "set to zero init" to overwrite the memsegment contents through load seems a bit inefficient.
Maybe we should instead let the MemSegment Constructor do it by adding an optional "init_zero" parameter.

@andrewstevens-infineon
Copy link
Collaborator

andrewstevens-infineon commented Aug 9, 2023 via email

@JoGei
Copy link
Member

JoGei commented Aug 9, 2023

Hi Andrew,

Yes, totally agree! Then we should maybe add a config based init type for memory segments like we use for length and origin: simple_mem_system.memseg_initelement_<nr>=<integer-literal> so for example ...

  • simple_mem_system.memseg_initelement_00=0xdeadbeef -> "specific integer literal"
  • simple_mem_system.memseg_initelement_00=-1 -> "all set"
  • simple_mem_system.memseg_initelement_00=0 -> "all reset"

and per default randomize, i.e., no .._initelement given, like we normally do it in the ETISS-SystemC Memory

Regards,

Johannes

@jokap11
Copy link
Contributor Author

jokap11 commented May 29, 2024

Considered your feedback @JoGei @andrewstevens-infineon!
The default case (simple_mem_system.memseg_initelement_ =0) initializes each MemSeg with randomized values
Otherwise, a specific uint8_t value is set to all elements in uint8_t* Array
(set by new simple_mem_system.memseg_initelement_ attribute)

@PhilippvK
Copy link
Member

Looks good for me.
@wysiwyng @JoGei what do you think?

@JoGei
Copy link
Member

JoGei commented Jun 10, 2024

Looks good for me. @wysiwyng @JoGei what do you think?

IMO, mostly fine, but it should be documented somewhere what the default behavior is.

If you randomize all program memory per default, users might experience unpredictable behavior when launching bad ELFs. E.g., getting different exceptions because of non-deterministic setups between runs.

Considered your feedback @JoGei @andrewstevens-infineon! The default case (simple_mem_system.memseg_initelement_ =0) initializes each MemSeg with randomized values Otherwise, a specific uint8_t value is set to all elements in uint8_t* Array (set by new simple_mem_system.memseg_initelement_ attribute)

With simple_mem_system.memseg_initelement_ =0, I would expect a "set to zero-value" for all memseg elements, not randomize all. Is it possible to parse a string literal first, e.g., simple_mem_system.memseg_initelement_ ="random"?
Because right now, we could not set the set value to "0" because it would be interpreted as "random"?

@wysiwyng
Copy link
Contributor

@JoGei we can't both parse a configuration value as integer and string, at least not without considerable hackery. I propose treating simple_mem_system.memseg_initelement_XX absent as "randomize", and all numerical values as "initialize to this value".

A workaround to this would be to treat simple_mem_system.memseg_initelement_XX as a string in any case, and then parse different options out of this string in C++. I.e. simple_mem_system.memseg_initelement_XX missing -> don't initialize at all simple_mem_system.memseg_initelement_XX = "random" -> randomize, simple_mem_system.memseg_initelement_XX = 0xdeadbeef" -> apply pattern repeated to memory.

Copy link
Contributor

@wysiwyng wysiwyng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking at minor code quality things

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep this file out of this PR, it has nothing to do with the memory init stuff

Comment on lines 124 to 130
// std::stringstream mem_msg;
// mem_msg << "This memory segment " << " is initialized with 0x" << std::hex << size_ << " bytes! \n";
// for (etiss::uint64 i = 0; i < size_; ++i)
// {
// mem_msg << static_cast<uint16_t>( mem_[i]) << ":";
// }
// etiss::log(etiss::INFO, mem_msg.str());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed


mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " bytes from input_image !";
etiss::log(etiss::INFO, mem_msg.str());
}else if (initVal != 0){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep code formatting consistent

}else if (initVal != 0){
mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " elements with value: " << static_cast<uint16_t>(initVal);
etiss::log(etiss::INFO, mem_msg.str());
}else{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep code formatting consistent

@wysiwyng
Copy link
Contributor

Lastly, I agree with @JoGei that this feature should be documented somewhere. Where that is I don't really know, as the previous changes to SimpleMemSystem are also only documented in the pull request that added them.

@jokap11 jokap11 force-pushed the initSimpleMemRegion branch from 023b7e3 to 9c00cbb Compare June 12, 2024 10:27
@jokap11
Copy link
Contributor Author

jokap11 commented Jun 12, 2024

@wysiwyng @JoGei @PhilippvK Thank you for your feedback:
I changed the simple_mem_system.memseg_initelement_XX element to a string type.
The default behavior behavior (not specified attr) allocates a randomized MemSegment.
(Documented with Doxygen at the MemSegment Constructor)
Otherwise the string is concatenated for the whole MemSegment - The tail is cut to prohibit overflow.

Copy link
Member

@JoGei JoGei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the std::string param= 0 default arguments.

self_allocated_ = true;
}
}

// Can be overwritten afterwards with load_elf
void memInit(uint8_t initVal = 0)
void memInit(std::string initString = 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string default argument should be = "" or removed since it now will be managed by etiss::initialize

MemSegment(etiss::uint64 start_addr, etiss::uint64 size, access_t mode, const std::string name,
etiss::uint8 *mem = nullptr, uint8_t initVal = 0)
etiss::uint8 *mem = nullptr, std::string initString = 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string default argument should be = "" or removed since it now will be managed by etiss::initialize

@wysiwyng
Copy link
Contributor

Still missing a case to "not initialize anything" when simple_mem_system.memseg_initelement_XX is not present in the config. You can use etiss::cfg().isSet to check whether a value is present in the configuration. Looks good otherwise.

@jokap11
Copy link
Contributor Author

jokap11 commented Jun 12, 2024

Still missing a case to "not initialize anything" when simple_mem_system.memseg_initelement_XX is not present in the config. You can use etiss::cfg().isSet to check whether a value is present in the configuration. Looks good otherwise.

I assumed that simple_mem_system.memseg_initelement_XX="" is no valid option anyways, that's why the default case in https://github.com/jokap11/etiss/blob/initSimpleMemRegion/src/SimpleMemSystem.cpp#L101 ="" is enough to filter this behavior. Or am I missing sth?
memseg_image_ filters in a similar fashion: https://github.com/jokap11/etiss/blob/master/src/SimpleMemSystem.cpp#L134

@wysiwyng
Copy link
Contributor

I assumed that simple_mem_system.memseg_initelement_XX="" is no valid option anyways

As far as I know the ini parser of ETISS accepts that input. What I mean is the case when the configuration file does not contain the key simple_mem_system.memseg_initelement_XX at all. I see the issue however, then the empty string would mean "random". I am also not quite happy with taking the string's characters verbatim to initialize the memory region, you would have to put binary into your configuration file. I think the possible input for simple_mem_system.memseg_initelement_XX should be trifold:

  1. nothing or absent: do nothing with the memory segment
  2. "random": randomize
  3. some hex number, starting with "0x" to make distinguishable: initialize with said number
  4. anything else: throw an error for invalid input

memseg_image_ filters in a similar fashion: https://github.com/jokap11/etiss/blob/master/src/SimpleMemSystem.cpp#L134

Yes, because it only needs to differentiate between two cases: something vaguely resembling a file path or empty. We want to differentiate between 3 cases: "Nothing", random, and some set value.

@jokap11 jokap11 requested a review from wysiwyng June 13, 2024 13:58
Comment on lines 164 to 166
}
else
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: keep formatting consistent

uint8_t hexVal = static_cast<uint8_t>(strtol(dataPtr, endPtr, 16));
mem_[i] = hexVal;

if (errno != 0){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errno != 0 only indicates an out-of-range condition for strtol, not an invalid string, see: https://en.cppreference.com/w/c/string/byte/strtol. To avoid this, use std::stoi: https://en.cppreference.com/w/cpp/string/basic_string/stol and handle the thrown exception(s).

Copy link
Contributor Author

@jokap11 jokap11 Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for clarifying. I was a bit confused after the errno=EINVAL option was not triggered with a false "hex val string": e.g 0xDEADBEEFh -> 0xDEADBEEF0 instead of leading to an errno!=0.
A weird thing though is that vscode leads me to this linux header:
https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno-base.h#L26
I assume that my work folder probably accesses unused files

Comment on lines 135 to 136
etiss::log(etiss::WARNING, "Hex Value MemSegment input is erronous (typo?)");
throw "MemSegmentInit for hex value is errnounous";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use etiss::FATALERROR to exit ETISS without having to resort to throw

for (etiss::uint64 i = 0; i < size_; ++i)
{
mem_[i] = random_char_(generator);
const char* dataPtr = initString.substr(i%initString.length(),1).c_str();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reading one hex character at a time will give you only 4 bits, you need 8

{
initString.erase(initString.begin(),initString.begin()+2);
std::stringstream mem_msg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mem_msg is unused here

Comment on lines 140 to 145
else if (initString.find("random") == 0 || initString.find("RANDOM") == 0)
{
const char* data = initString.c_str();
for (etiss::uint64 i = 0; i < size_; ++i)
{
mem_[i] = data[i%strlen(data)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where did the randomizing go?

Comment on lines 119 to 120
static std::default_random_engine generator{ static_cast<uint64_t>(0) };
std::uniform_int_distribution<int> random_char_{ 0, 255 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could move these lines to where they are actually needed

Comment on lines 157 to 173
} else if (initEleSet) {
if (initString.find("random") == 0 || initString.find("RANDOM")== 0) {
mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " random bytes !";
etiss::log(etiss::INFO, mem_msg.str());
} else if (initString.find("0x") == 0) {
mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " elements with hex value: " << initString;
etiss::log(etiss::INFO, mem_msg.str());
}
else
{
mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " elements with the string: " << initString;
etiss::log(etiss::INFO, mem_msg.str());
}
} else {
mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " random values !";
mem_msg << "The memory segment " << i << " is allocated uninitialized with length 0x" << std::hex << length << " !";
etiss::log(etiss::INFO, mem_msg.str());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these conditionals do is print debug messages, move the messages to MemSegment() where these differentiations have to be made anyways

Copy link
Contributor Author

@jokap11 jokap11 Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I lacked the local i var. Therfore I let this on this level. Otherwise I will remove just the i var since it is quite clear which MemSegment is initialized with which values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, i should not be necessary to keep here.

// Can be overwritten afterwards with load_elf
void memInit(std::string initString)
{
static std::default_random_engine generator{ static_cast<uint64_t>(0) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer having the seed (optionally) configurable via INI settings. Otherwise it would be quite hard to reproduce bugs,…

@jokap11 jokap11 requested review from wysiwyng, JoGei and PhilippvK June 14, 2024 09:18
@wysiwyng wysiwyng merged commit 6af4793 into tum-ei-eda:master Jun 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants