base: Add a size field to the Symbol object

Add a size field to the Symbol objects in the Symbol Table. This
allows client code to read the data associated with a symbol in cases
where the data type/size is not known beforehand (e.g. if an object's
size might be different between different versions of a
workload/kernel).

Access is mediated via the `sizeOrDefault()` method, which requires
client code to specify a fallback size. Since correct size data may
not be available (for example in legacy checkpoints), this forces the
client code to consider the 'missing size data' case.

Change-Id: If1a47463790b25beadf94f84382e3b7392ab2f04
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Richard Cooper
2023-11-30 12:11:28 +00:00
parent 2fbbdad618
commit 7ecff99c25
3 changed files with 45 additions and 3 deletions

View File

@@ -218,7 +218,8 @@ ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
}
loader::Symbol symbol(
binding, symbol_type, sym_name, sym.st_value);
binding, symbol_type, sym_name, sym.st_value,
sym.st_size);
if (_symtab.insert(symbol)) {
DPRINTF(Loader, "Symbol: %-40s value %#x.\n",

View File

@@ -111,6 +111,10 @@ SymbolTable::serialize(const std::string &base, CheckpointOut &cp) const
int i = 0;
for (auto &symbol: symbols) {
paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address());
if (symbol.sizeIsValid()) {
paramOut(cp, csprintf("%s.size_%d", base, i),
symbol.sizeOrDefault(0x0));
}
paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name());
paramOut(cp, csprintf("%s.binding_%d", base, i),
(int)symbol.binding());
@@ -128,17 +132,26 @@ SymbolTable::unserialize(const std::string &base, CheckpointIn &cp,
paramIn(cp, base + ".size", size);
for (int i = 0; i < size; ++i) {
Addr address;
size_t size;
std::string name;
Symbol::Binding binding = default_binding;
Symbol::SymbolType type = Symbol::SymbolType::Other;
paramIn(cp, csprintf("%s.addr_%d", base, i), address);
bool size_present = optParamIn(
cp, csprintf("%s.size_%d", base, i), size, false);
paramIn(cp, csprintf("%s.symbol_%d", base, i), name);
if (!optParamIn(cp, csprintf("%s.binding_%d", base, i), binding))
binding = default_binding;
if (!optParamIn(cp, csprintf("%s.type_%d", base, i), type))
type = Symbol::SymbolType::Other;
insert(Symbol(binding, type, name, address));
if (size_present) {
insert(Symbol(binding, type, name, address, size));
} else {
warn_once(
"warning: one or more Symbols does not have a valid size.");
insert(Symbol(binding, type, name, address));
}
}
}

View File

@@ -80,9 +80,16 @@ class Symbol
Other
};
Symbol(const Binding binding, const SymbolType type,
const std::string & name, const Addr addr, const size_t size)
: _binding(binding), _type(type), _name(name), _address(addr),
_size(size), _sizeIsValid(true)
{}
Symbol(const Binding binding, const SymbolType type,
const std::string & name, const Addr addr)
: _binding(binding), _type(type), _name(name), _address(addr)
: _binding(binding), _type(type), _name(name), _address(addr),
_size(0x0), _sizeIsValid(false)
{}
Symbol(const Symbol & other) = default;
@@ -112,11 +119,32 @@ class Symbol
_address = new_addr;
}
/**
* Return the Symbol size if it is valid, otherwise return the
* default value supplied.
*
* This method forces the client code to consider the possibility
* that the `SymbolTable` may contain `Symbol`s that do not have
* valid sizes.
*/
size_t sizeOrDefault(const size_t default_size) const {
return _sizeIsValid ? _size : default_size;
}
/**
* Return whether the Symbol size is valid or not.
*/
bool sizeIsValid() const {
return _sizeIsValid;
}
private:
Binding _binding;
SymbolType _type;
std::string _name;
Addr _address;
size_t _size;
bool _sizeIsValid;
};