[RFC] Move static archive dependencies into ld
Michael Matz
matz@suse.de
Mon Jun 5 15:32:49 GMT 2023
Heyho,
On Mon, 5 Jun 2023, Howard Chu wrote:
> What needs to happen to move this RFC forward? There seems to be at
> least some support for the idea (attached)
I was fiddling with also adding it to gold, and the support for threads
there confused me, so I put it on hold a bit. I did hack on it February,
and got it working, but couldn't really convince myself that I got the
dealing with the work-queues right. See below.
(Of the BFD part already send back then I'm convinced).
So, if someone could look over the gold patch and tell me if the workqueue
handling is somewhat okayish, we could proceed. (The "interesting" thing
about this is that I need to add items to a work-queue while it is
processed, _at the place right after it_, not merely scheduled to run
"eventually")
Ciao,
Michael.
-------------
diff --git a/gold/archive.cc b/gold/archive.cc
index 3983995d09a..5a439cfa412 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -190,7 +190,7 @@ const char Archive::sym64name[7] = { '/', 'S', 'Y', 'M', '6', '4', '/' };
Archive::Archive(const std::string& name, Input_file* input_file,
bool is_thin_archive, Dirsearch* dirpath, Task* task)
- : Library_base(task), name_(name), input_file_(input_file), armap_(),
+ : Library_base(task), libdeps_(NULL), name_(name), input_file_(input_file), armap_(),
armap_names_(), extended_names_(), armap_checked_(), seen_offsets_(),
members_(), is_thin_archive_(is_thin_archive), included_member_(false),
nested_archives_(), dirpath_(dirpath), num_members_(0),
@@ -1005,6 +1005,7 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
{
obj->layout(symtab, layout, sd);
obj->add_symbols(symtab, sd, layout);
+ this->maybe_handle_libdeps();
this->included_member_ = true;
}
delete sd;
@@ -1039,6 +1040,7 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
if (pluginobj != NULL)
{
pluginobj->add_symbols(symtab, NULL, layout);
+ this->maybe_handle_libdeps();
this->included_member_ = true;
return true;
}
@@ -1059,10 +1061,33 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
obj->add_symbols(symtab, &sd, layout);
}
+ this->maybe_handle_libdeps();
this->included_member_ = true;
return true;
}
+void
+Archive::maybe_handle_libdeps(void)
+{
+ if (this->included_member_)
+ return;
+ if (this->is_thin_archive_)
+ return;
+ fprintf(stderr, "handle_libdeps in %s\n", name_.c_str());
+ for (Archive::const_iterator p = this->begin();
+ p != this->end();
+ ++p)
+ {
+ fprintf(stderr, " %u %u %u %s\n", (unsigned)p->off, (unsigned)p->nested_off, (unsigned)p->size, p->name.c_str());
+ if (p->name == "__.LIBDEP")
+ {
+ const unsigned char* s = this->get_view(p->off + sizeof(Archive_header), p->size, false, false);
+ fprintf(stderr, " got it: %s\n", s);
+ this->libdeps_ = reinterpret_cast<const char*>(s);
+ }
+ }
+}
+
// Iterate over all unused symbols, and call the visitor class V for each.
void
@@ -1119,6 +1144,87 @@ Add_archive_symbols::locks(Task_locker* tl)
tl->add(this, this->archive_->token());
}
+/* Turn a string into an argvec. Copied from the original implementation
+ in the plugin, hence written in C. */
+
+static char **
+str2vec (char *in)
+{
+ char **res;
+ char *s, *first, *end;
+ char *sq, *dq;
+ int i;
+
+ end = in + strlen (in);
+ s = in;
+ while (isspace ((unsigned char) *s)) s++;
+ first = s;
+
+ i = 1;
+ while ((s = strchr (s, ' ')))
+ {
+ s++;
+ i++;
+ }
+ res = (char **)malloc ((i+1) * sizeof (char *));
+ if (!res)
+ return res;
+
+ i = 0;
+ sq = NULL;
+ dq = NULL;
+ res[0] = first;
+ for (s = first; *s; s++)
+ {
+ if (*s == '\\')
+ {
+ memmove (s, s+1, end-s-1);
+ end--;
+ }
+ if (isspace ((unsigned char) *s))
+ {
+ if (sq || dq)
+ continue;
+ *s++ = '\0';
+ while (isspace ((unsigned char) *s)) s++;
+ if (*s)
+ res[++i] = s;
+ }
+ if (*s == '\'' && !dq)
+ {
+ if (sq)
+ {
+ memmove (sq, sq+1, s-sq-1);
+ memmove (s-2, s+1, end-s-1);
+ end -= 2;
+ s--;
+ sq = NULL;
+ }
+ else
+ {
+ sq = s;
+ }
+ }
+ if (*s == '"' && !sq)
+ {
+ if (dq)
+ {
+ memmove (dq, dq+1, s-dq-1);
+ memmove (s-2, s+1, end-s-1);
+ end -= 2;
+ s--;
+ dq = NULL;
+ }
+ else
+ {
+ dq = s;
+ }
+ }
+ }
+ res[++i] = NULL;
+ return res;
+}
+
void
Add_archive_symbols::run(Workqueue* workqueue)
{
@@ -1135,6 +1241,79 @@ Add_archive_symbols::run(Workqueue* workqueue)
bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
this->input_objects_,
this->mapfile_);
+ if (added && this->archive_->libdeps_)
+ {
+ std::vector<Input_argument *> newinputs;
+ char **vec;
+ vec = str2vec (strdup (this->archive_->libdeps_));
+ if (vec)
+ {
+ std::string extra_search_path = "";
+ int i;
+ for (i = 0; vec[i]; i++)
+ {
+ if (vec[i][0] != '-')
+ fprintf (stderr, "ignoring libdep argument %s", vec[i]);
+ else if (vec[i][1] == 'l')
+ {
+ Input_file_argument file(
+ vec[i]+2,
+ Input_file_argument::INPUT_FILE_TYPE_LIBRARY,
+ extra_search_path.c_str(),
+ false,
+ this->archive_->input_file()->options());
+ Input_argument* input_argument = new Input_argument(file);
+ newinputs.push_back(input_argument);
+ }
+ else if (vec[i][1] == 'L')
+ extra_search_path = vec[i]+2;
+ else
+ fprintf (stderr, "ignoring libdep argument %s", vec[i]);
+ }
+ free (vec);
+ }
+
+ Task_token* this_blocker = NULL;
+ for (std::vector<Input_argument*>::const_iterator i = newinputs.begin();
+ i != newinputs.end();
+ ++i)
+ {
+ const Input_argument* arg = *i;
+
+ Task_token* next_blocker;
+ if (i != newinputs.end() - 1)
+ {
+ next_blocker = new Task_token(true);
+ next_blocker->add_blocker();
+ //fprintf(stderr, "XXX create new blocker %p\n", next_blocker);
+ }
+ else
+ {
+ next_blocker = this->next_blocker_;
+ /* The originally next task is blocked on _this_ task (about
+ to end right soon) and the last inserted new task. */
+ //next_blocker->add_blocker();
+ workqueue->add_blocker(next_blocker);
+ //fprintf(stderr, "XXX reuse old blocker %p\n", next_blocker);
+ }
+
+ //fprintf(stderr, "XXX queue with this_blocker %p\n", this_blocker);
+ workqueue->queue_soon(new Read_symbols(this->input_objects_,
+ this->symtab_,
+ this->layout_,
+ this->dirpath_,
+ 0,
+ this->mapfile_,
+ arg,
+ NULL,
+ NULL,
+ this_blocker,
+ next_blocker));
+ this_blocker = next_blocker;
+ }
+ }
+
+
this->archive_->unlock_nested_archives();
this->archive_->release();
diff --git a/gold/archive.h b/gold/archive.h
index 6e20d9c5f14..488563e7624 100644
--- a/gold/archive.h
+++ b/gold/archive.h
@@ -264,6 +264,8 @@ class Archive : public Library_base
no_export()
{ return this->no_export_; }
+ const char *libdeps_;
+
private:
Archive(const Archive&);
Archive& operator=(const Archive&);
@@ -340,6 +342,10 @@ class Archive : public Library_base
include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
Mapfile*, Symbol*, const char* why);
+ // Possibly search for and deal with recorded library dependencies.
+ void
+ maybe_handle_libdeps(void);
+
// Return whether we found this archive by searching a directory.
bool
searched_for() const
diff --git a/gold/token.h b/gold/token.h
index b58fcc2e1cd..723729c84b8 100644
--- a/gold/token.h
+++ b/gold/token.h
@@ -97,6 +97,7 @@ class Task_token
~Task_token()
{
+ //fprintf(stderr, "XXX dtor blocker %p\n", this);
gold_assert(this->blockers_ == 0);
gold_assert(this->writer_ == NULL);
}
@@ -121,6 +122,7 @@ class Task_token
void
add_writer(const Task* t)
{
+ //fprintf(stderr, "XXX add writer %p\n", this);
gold_assert(!this->is_blocker_ && this->writer_ == NULL);
this->writer_ = t;
}
@@ -158,6 +160,7 @@ class Task_token
bool
remove_blocker()
{
+ //fprintf(stderr, "XXX remove_blocker %p\n", this);
gold_assert(this->is_blocker_ && this->blockers_ > 0);
--this->blockers_;
this->writer_ = NULL;
@@ -168,6 +171,7 @@ class Task_token
bool
is_blocked() const
{
+ //fprintf(stderr, "XXX is_blocked %p\n", this);
gold_assert(this->is_blocker_);
return this->blockers_ > 0;
}
More information about the Binutils
mailing list