public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Michael Matz <matz@suse.de>
To: Howard Chu <hyc@symas.com>
Cc: binutils@sourceware.org
Subject: Re: [RFC] Move static archive dependencies into ld
Date: Mon, 5 Jun 2023 15:32:49 +0000 (UTC)	[thread overview]
Message-ID: <alpine.LSU.2.20.2306051500130.13548@wotan.suse.de> (raw)
In-Reply-To: <4b99cb5f-79a9-0a86-f675-81e4fa77e1b8@symas.com>

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;
   }

      reply	other threads:[~2023-06-05 15:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-17 15:03 Michael Matz
2023-02-17 20:53 ` Howard Chu
2023-04-13  9:10   ` Clément Chigot
2023-06-05 14:16   ` Howard Chu
2023-06-05 15:32     ` Michael Matz [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LSU.2.20.2306051500130.13548@wotan.suse.de \
    --to=matz@suse.de \
    --cc=binutils@sourceware.org \
    --cc=hyc@symas.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).