CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
213 lines
7.8 KiB
C++
213 lines
7.8 KiB
C++
/* The ExtentMap class. This class is similar std::map<rose_addr_t,rose_addr_t> where the two addresses are the starting
|
|
* offset and size. The main difference is that if two adjacent extents are added to the map they will be condensed into a
|
|
* single extent. This class is used to keep track of what parts of a binary file have been parsed, and is also used to
|
|
* manage string table free lists, among other things. */
|
|
|
|
#include <algorithm>
|
|
#include "util/StringUtility.h"
|
|
#include "ExtentMap.h"
|
|
#include <cstring>
|
|
#include <dyncompat/foreach.hpp>
|
|
|
|
#define DUMP_FIELD_WIDTH 64
|
|
|
|
Extent toExtent(const AddressInterval &x) {
|
|
return x.isEmpty() ? Extent() : Extent::inin(x.least(), x.greatest());
|
|
}
|
|
|
|
AddressInterval toAddressInterval(const Extent &x) {
|
|
return x.empty() ? AddressInterval() : AddressInterval::hull(x.first(), x.last());
|
|
}
|
|
|
|
ExtentMap toExtentMap(const AddressIntervalSet &x) {
|
|
ExtentMap retval;
|
|
DYN_FOREACH (const AddressInterval &interval, x.intervals())
|
|
retval.insert(toExtent(interval));
|
|
return retval;
|
|
}
|
|
|
|
AddressIntervalSet toAddressIntervalSet(const ExtentMap &x) {
|
|
AddressIntervalSet retval;
|
|
for (ExtentMap::const_iterator iter=x.begin(); iter!=x.end(); ++iter)
|
|
retval.insert(toAddressInterval(iter->first));
|
|
return retval;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream &out, const AddressInterval &x) {
|
|
if (x.isEmpty()) {
|
|
out <<"empty";
|
|
} else if (x.isSingleton()) {
|
|
out <<StringUtility::addrToString(x.least());
|
|
} else {
|
|
out <<"[" <<StringUtility::addrToString(x.least()) <<"," <<StringUtility::addrToString(x.greatest()) <<"]";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream &out, const AddressIntervalSet &x) {
|
|
out <<"{";
|
|
DYN_FOREACH (const AddressInterval &interval, x.intervals())
|
|
out <<" " <<interval;
|
|
out <<" }";
|
|
return out;
|
|
}
|
|
|
|
/** Class method comparing two extents. The return value is one of the following letters, depending on how extent A is related
|
|
* to extent B:
|
|
* C (congruent): A and B are congruent
|
|
* L (left): A is left of B
|
|
* R (right): A is right of B
|
|
* O (outer): A contains B, but A and B are not congruent
|
|
* I (inner): A is contained by B, but A and B are not congruent
|
|
* B (beginning): A overlaps with the beginning of B but does not contain B
|
|
* E (ending): A overlaps with the end of B but does not contain B */
|
|
char
|
|
ExtentMap::category(const Extent &a, const Extent &b)
|
|
{
|
|
if (a.relaxed_first()==b.relaxed_first() && a.size()==b.size())
|
|
return 'C';
|
|
if (a.relaxed_first()+a.size() <= b.relaxed_first())
|
|
return 'L';
|
|
if (a.relaxed_first() >= b.relaxed_first()+b.size())
|
|
return 'R';
|
|
if (a.relaxed_first() <= b.relaxed_first() && a.relaxed_first()+a.size() >= b.relaxed_first()+b.size())
|
|
return 'O';
|
|
if (a.relaxed_first() >= b.relaxed_first() && a.relaxed_first()+a.size() <= b.relaxed_first()+b.size())
|
|
return 'I';
|
|
if (a.relaxed_first() <= b.relaxed_first()) /*already know a.first+a.size > b.first*/
|
|
return 'B';
|
|
return 'E';
|
|
}
|
|
|
|
/** Allocate an extent of the specified size (best fit first) from the extent map, removing the returned extent from the map. */
|
|
Extent
|
|
ExtentMap::allocate_best_fit(rose_addr_t size)
|
|
{
|
|
iterator found = best_fit(size, begin());
|
|
if (found==end())
|
|
throw std::bad_alloc();
|
|
Extent retval(found->first.first(), size);
|
|
erase(retval);
|
|
return retval;
|
|
}
|
|
|
|
/** Allocate an extent of the specified size (first fit) from the extent map, removing the returned extent from the map. */
|
|
Extent
|
|
ExtentMap::allocate_first_fit(rose_addr_t size)
|
|
{
|
|
iterator found = first_fit(size, begin());
|
|
if (found==end())
|
|
throw std::bad_alloc();
|
|
Extent retval(found->first.first(), size);
|
|
erase(retval);
|
|
return retval;
|
|
}
|
|
|
|
/** Allocate the specified extent, which must be in the free list. */
|
|
void
|
|
ExtentMap::allocate_at(const Extent &request)
|
|
{
|
|
ROSE_ASSERT(subtract_from(request).size()==0); /*entire request should be on free list*/
|
|
erase(request);
|
|
}
|
|
|
|
#if 0 /* NOT NEEDED BY ANYTHING? [RPM 2011-10-18] */
|
|
/** Precipitates individual extents into larger extents by combining individual extents that are separated by an amount less
|
|
* than or equal to some specified @p reagent value. Individual elements that would have been adjacent have already
|
|
* been combined by the other modifying methods (insert, erase, etc). */
|
|
void
|
|
ExtentMap::precipitate(rose_addr_t reagent)
|
|
{
|
|
abort(); // NOT IMPLEMENTED
|
|
ExtentMap result;
|
|
for (iterator i=begin(); i!=end(); /*void*/) {
|
|
ExtentPair left = *i++;
|
|
for (/*void*/; i!=end() && left.first+left.second+reagent >= i->first; i++)
|
|
left.second = (i->first + i->second) - left.first;
|
|
result.insert(left);
|
|
}
|
|
*this = result;
|
|
}
|
|
#endif
|
|
|
|
#if 0 /* NOT NEEDED BY ANYTHING? [RPM 2011-10-18] */
|
|
/** Find the extent pair that contains the specified address. Throw std::bad_alloc() if the address is not found. */
|
|
ExtentPair
|
|
ExtentMap::find_address(rose_addr_t addr) const
|
|
{
|
|
const_iterator i = upper_bound(addr);
|
|
RangeMapType::const_iterator i2 = ranges.find(addr);
|
|
if (i==begin()) {
|
|
assert(i2==ranges.end());
|
|
throw std::bad_alloc();
|
|
}
|
|
--i;
|
|
if (i->first+i->second <= addr) {
|
|
assert(i2==ranges.end());
|
|
throw std::bad_alloc();
|
|
}
|
|
|
|
assert(i->first==i2->first.begin);
|
|
assert(i->second==i2->first.size);
|
|
return *i;
|
|
}
|
|
#endif
|
|
|
|
#if 0 /* NOT NEEDED BY ANYTHING? [RPM 2011-10-18] */
|
|
/** Determines if specified bytes are in the extent map. If every byte of the specified extent is defined by the extent map,
|
|
* then this function returns true, otherwise false. */
|
|
bool
|
|
ExtentMap::exists_all(ExtentPair what) const
|
|
{
|
|
while (what.second>0) {
|
|
try {
|
|
ExtentPair found = find_address(what.first);
|
|
assert(found.second > 0);
|
|
assert(found.first <= what.first);
|
|
assert(what.first <= found.first + found.second);
|
|
rose_addr_t nfound = std::min(what.second, found.second-(what.first-found.first));
|
|
what.first = found.first + found.second;
|
|
what.second -= nfound;
|
|
} catch (const std::bad_alloc&) { // thrown by find_address()
|
|
assert(!ranges.contains(RangeType(what.first, what.second)));
|
|
return false;
|
|
}
|
|
}
|
|
assert(ranges.contains(RangeType(what.first, what.second)));
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
ExtentMap::dump_extents(std::ostream &o, const std::string &prefix, const std::string &label) const
|
|
{
|
|
using namespace StringUtility;
|
|
size_t idx=0;
|
|
for (const_iterator i=begin(); i!=end(); ++i, ++idx) {
|
|
o <<prefix <<(label.empty()?std::string("Extent"):label) <<"[" <<idx <<"]"
|
|
<<" = offset " <<unsignedToHex(i->first.first())
|
|
<<" for " <<unsignedToHex(i->first.size()) <<(1==i->first.size()?" byte":" bytes")
|
|
<<" ending at " <<unsignedToHex(i->first.first() + i->first.size()) <<"\n";
|
|
}
|
|
}
|
|
|
|
|
|
/** Print info about an extent map. This is a little different format than the ostream "<<" operator. */
|
|
void
|
|
ExtentMap::dump_extents(FILE *f, const char *prefix, const char *label, bool pad) const
|
|
{
|
|
char p[4096];
|
|
size_t idx=0;
|
|
for (const_iterator i=begin(); i!=end(); ++i, ++idx) {
|
|
if (!label) label = "Extent";
|
|
sprintf(p, "%s%s[%zd]", prefix, label, idx);
|
|
int w = pad ? std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p)) : 1;
|
|
fprintf(f, "%s%-*s = offset 0x%08" PRIx64 " (%" PRIu64 "),"
|
|
" for 0x%08" PRIx64 " (%" PRIu64 ") byte%s,"
|
|
" ending at 0x%08" PRIx64 " (%" PRIu64 ")\n",
|
|
p, w, "", i->first.first(), i->first.first(),
|
|
i->first.size(), i->first.size(), 1==i->first.size()?"":"s",
|
|
i->first.first()+i->first.size(), i->first.first()+i->first.size());
|
|
}
|
|
}
|