Skip to content

Commit 14bbd4b

Browse files
committed
Add an "openImage", and rename "getImage" to "findImage"
This makes it clear that "findImage" is not just opening a path, but gives the facility to do that anyway.
1 parent 427e486 commit 14bbd4b

File tree

14 files changed

+68
-56
lines changed

14 files changed

+68
-56
lines changed

canal.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ mainExcept(int argc, char *argv[])
303303
.parse(argc, argv);
304304

305305
if (argc - optind >= 2) {
306-
exec = context.getImage(argv[optind]);
306+
exec = context.openImage(argv[optind]);
307307
optind++;
308308
}
309309

context.cc

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ Context::Context()
3030
}
3131

3232
std::shared_ptr<Dwarf::Info>
33-
Context::getDwarf(const std::filesystem::path &filename)
33+
Context::findDwarf(const std::filesystem::path &filename)
3434
{
35-
return getDwarf(getImage(filename));
35+
return findDwarf(findImage(filename));
3636
}
3737

3838
debuginfod_client *
@@ -66,13 +66,13 @@ Context::debuginfod()
6666

6767

6868
std::shared_ptr<Dwarf::Info>
69-
Context::getDwarf(const Elf::BuildID &bid)
69+
Context::findDwarf(const Elf::BuildID &bid)
7070
{
71-
return getDwarf(getImage(bid));
71+
return findDwarf(findImage(bid));
7272
}
7373

7474
Dwarf::Info::sptr
75-
Context::getDwarf(Elf::Object::sptr object)
75+
Context::findDwarf(Elf::Object::sptr object)
7676
{
7777
auto it = dwarfCache.find(object);
7878
counters.dwarfLookups++;
@@ -154,6 +154,11 @@ Context::getImageIfLoaded(const Container &ctr, const typename Container::key_ty
154154
return {};
155155
}
156156

157+
std::shared_ptr<Elf::Object>
158+
Context::openImage(const std::filesystem::path &path, int fd, bool isDebug) {
159+
return std::make_shared<Elf::Object>(*this, std::make_shared<MmapReader>(*this, path, fd) , isDebug);
160+
}
161+
157162
/*
158163
* Find an image from a name, caching in container, and using "paths" as potential prefixes for name
159164
*/
@@ -178,7 +183,7 @@ Context::getImageInPath(const std::vector<std::filesystem::path> &paths, NameMap
178183
}
179184
}
180185
try {
181-
res = std::make_shared<Elf::Object>(*this, std::make_shared<MmapReader>(*this, path) , isDebug);
186+
res = openImage( path, -1, isDebug );
182187
break;
183188
}
184189
catch (const std::exception &ex) {
@@ -199,7 +204,7 @@ Context::getImageInPath(const std::vector<std::filesystem::path> &paths, NameMap
199204
* get an image from a filename
200205
*/
201206
std::shared_ptr<Elf::Object>
202-
Context::getImage(const std::filesystem::path &name) {
207+
Context::findImage(const std::filesystem::path &name) {
203208
if (options.noLocalFiles)
204209
return nullptr;
205210
return getImageInPath(exePrefixes, imageByName, name, false, false);
@@ -208,7 +213,7 @@ Context::getImage(const std::filesystem::path &name) {
208213
/*
209214
* get an image, given its build ID. It may be a debug image, or an
210215
* "executable". We first defer to the filesystem, using the string versions of
211-
* "getImage", and a broken-down form of the build id, with the first octet of
216+
* "findImage", and a broken-down form of the build id, with the first octet of
212217
* the build-id being a directlry name, and the remainder being the filename,
213218
* with a possible suffix. This allows us to find things of the form
214219
* /usr/lib/debug/build-id/NN/NNNNNNNNNNNNNNNNNNNN.debug for example. The
@@ -218,42 +223,42 @@ Context::getImage(const std::filesystem::path &name) {
218223

219224
std::shared_ptr<Elf::Object> Context::getImageImpl( const Elf::BuildID &bid, bool isDebug) {
220225

221-
IdMap &container = isDebug ? debugImageByID : imageByID;
222-
NameMap &nameContainer = isDebug ? debugImageByName : imageByName;
223-
std::vector<std::filesystem::path> &paths = isDebug ? debugBuildIdPrefixes : exeBuildIdPrefixes;
224-
226+
Elf::Object::sptr res;
225227
if (!bid || options.noBuildIds)
226228
return nullptr;
229+
IdMap &container = isDebug ? debugImageByID : imageByID;
230+
227231
std::optional<Elf::Object::sptr> cached = getImageIfLoaded( container, bid, isDebug );
228232
if (cached)
229233
return *cached;
230234

231-
std::stringstream bucket;
232-
bucket << AsHex( bid[ 0 ] );
233-
std::stringstream rest;
234-
rest << AsHex(std::views::all(bid) | std::views::drop(1));
235-
if ( isDebug )
236-
rest << ".debug";
235+
if (!options.noLocalFiles) {
236+
NameMap &nameContainer = isDebug ? debugImageByName : imageByName;
237+
std::vector<std::filesystem::path> &paths = isDebug ? debugBuildIdPrefixes : exeBuildIdPrefixes;
237238

238-
std::filesystem::path bidpath = std::filesystem::path( bucket.str() ) / std::filesystem::path( rest.str() );
239+
std::stringstream bucket;
240+
bucket << AsHex( bid[ 0 ] );
241+
std::stringstream rest;
242+
rest << AsHex(std::views::all(bid) | std::views::drop(1));
243+
if ( isDebug )
244+
rest << ".debug";
239245

240-
Elf::Object::sptr res = getImageInPath(paths, nameContainer, bidpath, isDebug, true);
246+
std::filesystem::path bidpath = std::filesystem::path( bucket.str() ) / std::filesystem::path( rest.str() );
247+
res = getImageInPath(paths, nameContainer, bidpath, isDebug, true);
248+
}
241249
#ifdef DEBUGINFOD
242250
if (!res && debuginfod()) {
243-
char *path;
251+
char *path = nullptr;
244252
int progress = 0;
245253
debuginfod_set_user_data(debuginfod(), &progress);
246254
int fd = (isDebug ? debuginfod_find_debuginfo : debuginfod_find_executable)
247255
(debuginfod(), bid.data(), int( bid.size() ), &path);
248256
if (progress > 0) {
257+
// If we reported progress at least once, move to the next line
249258
std::cerr << "\n";
250259
}
251260
if (fd >= 0) {
252-
// Wrap the fd in a reader, and then a cache reader...
253-
std::shared_ptr<Reader> reader = std::make_shared<FileReader>(*this, path, fd );
254-
reader = std::make_shared<CacheReader>(reader);
255-
// and then wrap the lot in an ELF object.
256-
res = std::make_shared<Elf::Object>( *this, reader, true );
261+
res = openImage( path, fd, true );
257262
free(path);
258263
if (verbose)
259264
*debug << "fetched " << *res->io << " for " << bid << " with debuginfod\n";
@@ -267,7 +272,7 @@ std::shared_ptr<Elf::Object> Context::getImageImpl( const Elf::BuildID &bid, boo
267272
}
268273

269274
std::shared_ptr<Elf::Object>
270-
Context::getDebugImage(const std::filesystem::path &name) {
275+
Context::findDebugImage(const std::filesystem::path &name) {
271276
return getImageInPath(debugPrefixes, debugImageByName, name, true, false);
272277
}
273278

@@ -279,8 +284,8 @@ int debuginfod_find_executable (debuginfod_client *, const unsigned char *, int,
279284
}
280285
#endif
281286

282-
std::shared_ptr<Elf::Object> Context::getDebugImage(const Elf::BuildID &bid) { return getImageImpl(bid, true); }
283-
std::shared_ptr<Elf::Object> Context::getImage(const Elf::BuildID &bid) { return getImageImpl(bid, false); }
287+
std::shared_ptr<Elf::Object> Context::findDebugImage(const Elf::BuildID &bid) { return getImageImpl(bid, true); }
288+
std::shared_ptr<Elf::Object> Context::findImage(const Elf::BuildID &bid) { return getImageImpl(bid, false); }
284289

285290
std::shared_ptr<const Reader>
286291
Context::loadFile(const std::filesystem::path &path) {

dwarf_info.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ Info::sptr
262262
Info::getAltDwarf() const
263263
{
264264
if (!altImageLoaded) {
265-
altDwarf = elf->context.getDwarf(getAltImageName());
265+
altDwarf = elf->context.findDwarf(getAltImageName());
266266
altImageLoaded = true;
267267
}
268268
if (altDwarf == nullptr)

elf.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ Object::getDebug() const
606606

607607
// Use the build ID to find debug data.
608608
auto bid = getBuildID();
609-
debugObject = context.getDebugImage(bid);
609+
debugObject = context.findDebugImage(bid);
610610

611611
// If that doesn't work, maybe the gnu_debuglink is valid?
612612
if (!debugObject) {
@@ -615,7 +615,7 @@ Object::getDebug() const
615615
if (hdr) {
616616
auto link = hdr.io()->readString(0);
617617
auto dir = std::filesystem::path(stringify(*io)).parent_path();
618-
debugObject = context.getDebugImage(dir / link);
618+
debugObject = context.findDebugImage(dir / link);
619619
}
620620
}
621621

hdmp.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ void printStack(std::ostream &os, std::shared_ptr<Procman::Process> &proc, const
3232
os << "\t" << name << "+" << uintptr_t(frames[i]) - elfReloc - sym.st_value;
3333
}
3434

35-
auto dwarf = proc->context.getDwarf(elf);
35+
auto dwarf = proc->context.findDwarf(elf);
3636
if (dwarf) {
3737
auto sep = "in";
3838
for (auto &&[file, line] : dwarf->sourceFromAddr(frameip - elfReloc)) {
@@ -113,7 +113,7 @@ main(int argc, char *argv[])
113113
for (int c; (c = getopt(argc, argv, "e:fab")) != -1; ) {
114114
switch (c) {
115115
case 'e':
116-
exec = context.getImage(optarg);
116+
exec = context.openImage(optarg);
117117
break;
118118
case 'f':
119119
options.insert(heap_recentfree);

libpstack/context.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,22 @@ class Context {
7373
int openfile(const std::filesystem::path &filename, int mode = O_RDONLY, int umask = 0777);
7474
int openFileDirect(const std::filesystem::path &name_, int mode, int mask);
7575

76-
std::shared_ptr<Elf::Object> getImage(const std::filesystem::path &name);
77-
std::shared_ptr<Elf::Object> getImage(const Elf::BuildID &);
76+
// Unlike getImage, this will not search paths - name must be a local file path.
77+
std::shared_ptr<Elf::Object> openImage(const std::filesystem::path &name, int fd = -1, bool isDebug = false);
78+
79+
// Get an image, searching as required.
80+
std::shared_ptr<Elf::Object> findImage(const std::filesystem::path &name);
81+
std::shared_ptr<Elf::Object> findImage(const Elf::BuildID &);
7882

7983
// Debug images are specifically those with the text/data stripped, and just
8084
// the Dwarf/symbol table left.
81-
std::shared_ptr<Elf::Object> getDebugImage(const std::filesystem::path &name);
82-
std::shared_ptr<Elf::Object> getDebugImage(const Elf::BuildID &);
85+
std::shared_ptr<Elf::Object> findDebugImage(const std::filesystem::path &name);
86+
std::shared_ptr<Elf::Object> findDebugImage(const Elf::BuildID &);
8387

84-
std::shared_ptr<Dwarf::Info> getDwarf(const std::filesystem::path &);
85-
std::shared_ptr<Dwarf::Info> getDwarf(const Elf::BuildID &);
88+
std::shared_ptr<Dwarf::Info> findDwarf(const std::filesystem::path &);
89+
std::shared_ptr<Dwarf::Info> findDwarf(const Elf::BuildID &);
8690

87-
std::shared_ptr<Dwarf::Info> getDwarf(std::shared_ptr<Elf::Object>);
91+
std::shared_ptr<Dwarf::Info> findDwarf(std::shared_ptr<Elf::Object>);
8892
void flush(std::shared_ptr<Elf::Object> o);
8993
std::filesystem::path procname(pid_t pid, const std::filesystem::path &base);
9094

libpstack/proc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ struct MappedObject {
228228
}
229229
Elf::Object::sptr object(Context &ctx) {
230230
if (objptr_ == nullptr)
231-
objptr_ = ctx.getImage(bid_);
231+
objptr_ = ctx.findImage(bid_);
232232
if (objptr_ == nullptr)
233-
objptr_ = ctx.getImage(name_);
233+
objptr_ = ctx.findImage(name_);
234234
return objptr_;
235235
}
236236
MappedObject(std::string_view name, Elf::BuildID bid, Elf::Object::sptr objptr = {}) :

libpstack/reader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class MemReader : public Reader {
161161

162162
class MmapReader final : public MemReader {
163163
public:
164-
MmapReader(Context &, const std::string &name_);
164+
MmapReader(Context &, const std::string &name_, int fd = - 1);
165165
~MmapReader() override;
166166
MmapReader(const MmapReader &) = delete;
167167
MmapReader(MmapReader &&) = delete;

live.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ LiveReader::LiveReader(Context &c, pid_t pid, const std::string &base) : FileRea
2424

2525
Elf::Object::sptr
2626
LiveProcess::executableImage() {
27-
return context.getImage(context.procname(getPID(), "exe"));
27+
return context.findImage(context.procname(getPID(), "exe"));
2828
}
2929

3030
LiveProcess::LiveProcess(Context &context, Elf::Object::sptr &ex, pid_t pid_, bool alreadyStopped)

process.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ Process::load()
202202
Dwarf::Info::sptr
203203
Process::getDwarf(Elf::Object::sptr elf) const
204204
{
205-
return context.getDwarf(elf);
205+
return context.findDwarf(elf);
206206
}
207207

208208

@@ -350,14 +350,14 @@ Process::processAUXV(const Reader &auxio)
350350
io->read(noteVa + sizeof n + 4, n.n_descsz, (char *)data.data());
351351
if (context.verbose)
352352
*context.debug << "build ID From AT_PHDR: " << Elf::BuildID(data) << "\n";
353-
execImage = context.getImage(Elf::BuildID{data});
353+
execImage = context.findImage(Elf::BuildID{data});
354354
break;
355355
}
356356
}
357357
}
358358

359359
if (!execImage && exeName != "")
360-
execImage = context.getImage(exeName);
360+
execImage = context.findImage(exeName);
361361
if (!execImage)
362362
execImage = executableImage(); // default to whatever the process can give us (eg, mmap /proc/<>/exe)
363363
}

0 commit comments

Comments
 (0)