1 // export.cc -- Export declarations in Go frontend.
2 
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6 
7 #include "go-system.h"
8 
9 #include "go-sha1.h"
10 #include "go-c.h"
11 
12 #include "gogo.h"
13 #include "types.h"
14 #include "statements.h"
15 #include "export.h"
16 
17 #include "go-linemap.h"
18 #include "backend.h"
19 
20 // This file handles exporting global declarations.
21 
22 // Class Export.
23 
24 const int Export::magic_len;
25 
26 // Current version magic string.
27 const char Export::cur_magic[Export::magic_len] =
28   {
29     'v', '2', ';', '\n'
30   };
31 
32 // Magic string for previous version (still supported)
33 const char Export::v1_magic[Export::magic_len] =
34   {
35     'v', '1', ';', '\n'
36   };
37 
38 const int Export::checksum_len;
39 
40 // Constructor.
41 
Export(Stream * stream)42 Export::Export(Stream* stream)
43   : stream_(stream), type_refs_(), type_index_(1), packages_()
44 {
45   go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
46 }
47 
48 // A functor to sort Named_object pointers by name.
49 
50 struct Sort_bindings
51 {
52   bool
operator ()Sort_bindings53   operator()(const Named_object* n1, const Named_object* n2) const
54   { return n1->name() < n2->name(); }
55 };
56 
57 // Return true if we should export NO.
58 
59 static bool
should_export(Named_object * no)60 should_export(Named_object* no)
61 {
62   // We only export objects which are locally defined.
63   if (no->package() != NULL)
64     return false;
65 
66   // We don't export packages.
67   if (no->is_package())
68     return false;
69 
70   // We don't export hidden names.
71   if (Gogo::is_hidden_name(no->name()))
72     return false;
73 
74   // We don't export nested functions.
75   if (no->is_function() && no->func_value()->enclosing() != NULL)
76     return false;
77 
78   // We don't export thunks.
79   if (no->is_function() && Gogo::is_thunk(no))
80     return false;
81 
82   // Methods are exported with the type, not here.
83   if (no->is_function()
84       && no->func_value()->type()->is_method())
85     return false;
86   if (no->is_function_declaration()
87       && no->func_declaration_value()->type()->is_method())
88     return false;
89 
90   // Don't export dummy global variables created for initializers when
91   // used with sinks.
92   if (no->is_variable() && no->name()[0] == '_' && no->name()[1] == '.')
93     return false;
94 
95   return true;
96 }
97 
98 // Export those identifiers marked for exporting.
99 
100 void
export_globals(const std::string & package_name,const std::string & prefix,const std::string & pkgpath,const std::map<std::string,Package * > & packages,const std::map<std::string,Package * > & imports,const std::string & import_init_fn,const Import_init_set & imported_init_fns,const Bindings * bindings)101 Export::export_globals(const std::string& package_name,
102 		       const std::string& prefix,
103 		       const std::string& pkgpath,
104 		       const std::map<std::string, Package*>& packages,
105 		       const std::map<std::string, Package*>& imports,
106 		       const std::string& import_init_fn,
107                        const Import_init_set& imported_init_fns,
108 		       const Bindings* bindings)
109 {
110   // If there have been any errors so far, don't try to export
111   // anything.  That way the export code doesn't have to worry about
112   // mismatched types or other confusions.
113   if (saw_errors())
114     return;
115 
116   // Export the symbols in sorted order.  That will reduce cases where
117   // irrelevant changes to the source code affect the exported
118   // interface.
119   std::vector<Named_object*> exports;
120   exports.reserve(bindings->size_definitions());
121 
122   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
123        p != bindings->end_definitions();
124        ++p)
125     if (should_export(*p))
126       exports.push_back(*p);
127 
128   for (Bindings::const_declarations_iterator p =
129 	 bindings->begin_declarations();
130        p != bindings->end_declarations();
131        ++p)
132     {
133       // We export a function declaration as it may be implemented in
134       // supporting C code.  We do not export type declarations.
135       if (p->second->is_function_declaration()
136 	  && should_export(p->second))
137 	exports.push_back(p->second);
138     }
139 
140   std::sort(exports.begin(), exports.end(), Sort_bindings());
141 
142   // Although the export data is readable, at least this version is,
143   // it is conceptually a binary format.  Start with a four byte
144   // version number.
145   this->write_bytes(Export::cur_magic, Export::magic_len);
146 
147   // The package name.
148   this->write_c_string("package ");
149   this->write_string(package_name);
150   this->write_c_string(";\n");
151 
152   // The prefix or package path, used for all global symbols.
153   if (prefix.empty())
154     {
155       go_assert(!pkgpath.empty());
156       this->write_c_string("pkgpath ");
157       this->write_string(pkgpath);
158     }
159   else
160     {
161       this->write_c_string("prefix ");
162       this->write_string(prefix);
163     }
164   this->write_c_string(";\n");
165 
166   this->write_packages(packages);
167 
168   this->write_imports(imports);
169 
170   this->write_imported_init_fns(package_name, import_init_fn,
171 				imported_init_fns);
172 
173   // FIXME: It might be clever to add something about the processor
174   // and ABI being used, although ideally any problems in that area
175   // would be caught by the linker.
176 
177   for (std::vector<Named_object*>::const_iterator p = exports.begin();
178        p != exports.end();
179        ++p)
180     (*p)->export_named_object(this);
181 
182   std::string checksum = this->stream_->checksum();
183   std::string s = "checksum ";
184   for (std::string::const_iterator p = checksum.begin();
185        p != checksum.end();
186        ++p)
187     {
188       unsigned char c = *p;
189       unsigned int dig = c >> 4;
190       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
191       dig = c & 0xf;
192       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
193     }
194   s += ";\n";
195   this->stream_->write_checksum(s);
196 }
197 
198 // Sort packages.
199 
200 static bool
packages_compare(const Package * a,const Package * b)201 packages_compare(const Package* a, const Package* b)
202 {
203   return a->package_name() < b->package_name();
204 }
205 
206 // Write out all the known packages whose pkgpath symbol is not a
207 // simple transformation of the pkgpath, so that the importing code
208 // can reliably know it.
209 
210 void
write_packages(const std::map<std::string,Package * > & packages)211 Export::write_packages(const std::map<std::string, Package*>& packages)
212 {
213   // Sort for consistent output.
214   std::vector<Package*> out;
215   for (std::map<std::string, Package*>::const_iterator p = packages.begin();
216        p != packages.end();
217        ++p)
218     {
219       if (p->second->pkgpath_symbol()
220 	  != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
221 	out.push_back(p->second);
222     }
223 
224   std::sort(out.begin(), out.end(), packages_compare);
225 
226   for (std::vector<Package*>::const_iterator p = out.begin();
227        p != out.end();
228        ++p)
229     {
230       this->write_c_string("package ");
231       this->write_string((*p)->package_name());
232       this->write_c_string(" ");
233       this->write_string((*p)->pkgpath());
234       this->write_c_string(" ");
235       this->write_string((*p)->pkgpath_symbol());
236       this->write_c_string(";\n");
237     }
238 }
239 
240 // Sort imported packages.
241 
242 static bool
import_compare(const std::pair<std::string,Package * > & a,const std::pair<std::string,Package * > & b)243 import_compare(const std::pair<std::string, Package*>& a,
244 	       const std::pair<std::string, Package*>& b)
245 {
246   return a.first < b.first;
247 }
248 
249 // Write out the imported packages.
250 
251 void
write_imports(const std::map<std::string,Package * > & imports)252 Export::write_imports(const std::map<std::string, Package*>& imports)
253 {
254   // Sort the imports for more consistent output.
255   std::vector<std::pair<std::string, Package*> > sorted_imports;
256   for (std::map<std::string, Package*>::const_iterator p = imports.begin();
257        p != imports.end();
258        ++p)
259     sorted_imports.push_back(std::make_pair(p->first, p->second));
260 
261   std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
262 
263   for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
264 	 sorted_imports.begin();
265        p != sorted_imports.end();
266        ++p)
267     {
268       this->write_c_string("import ");
269       this->write_string(p->second->package_name());
270       this->write_c_string(" ");
271       this->write_string(p->second->pkgpath());
272       this->write_c_string(" \"");
273       this->write_string(p->first);
274       this->write_c_string("\";\n");
275 
276       this->packages_.insert(p->second);
277     }
278 }
279 
280 void
add_init_graph_edge(Init_graph * init_graph,unsigned src,unsigned sink)281 Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink)
282 {
283   Init_graph::iterator it = init_graph->find(src);
284   if (it != init_graph->end())
285     it->second.insert(sink);
286   else
287     {
288       std::set<unsigned> succs;
289       succs.insert(sink);
290       (*init_graph)[src] = succs;
291     }
292 }
293 
294 // Constructs the imported portion of the init graph, e.g. those
295 // edges that we read from imported packages.
296 
297 void
populate_init_graph(Init_graph * init_graph,const Import_init_set & imported_init_fns,const std::map<std::string,unsigned> & init_idx)298 Export::populate_init_graph(Init_graph* init_graph,
299                             const Import_init_set& imported_init_fns,
300                             const std::map<std::string, unsigned>& init_idx)
301 {
302   for (Import_init_set::const_iterator p = imported_init_fns.begin();
303        p != imported_init_fns.end();
304        ++p)
305     {
306       const Import_init* ii = *p;
307       std::map<std::string, unsigned>::const_iterator srcit =
308           init_idx.find(ii->init_name());
309       go_assert(srcit != init_idx.end());
310       unsigned src = srcit->second;
311       for (std::set<std::string>::const_iterator pci = ii->precursors().begin();
312            pci != ii->precursors().end();
313            ++pci)
314 	{
315 	  std::map<std::string, unsigned>::const_iterator it =
316 	      init_idx.find(*pci);
317 	  go_assert(it != init_idx.end());
318 	  unsigned sink = it->second;
319 	  add_init_graph_edge(init_graph, src, sink);
320 	}
321     }
322 }
323 
324 // Write out the initialization functions which need to run for this
325 // package.
326 
327 void
write_imported_init_fns(const std::string & package_name,const std::string & import_init_fn,const Import_init_set & imported_init_fns)328 Export::write_imported_init_fns(const std::string& package_name,
329                                 const std::string& import_init_fn,
330                                 const Import_init_set& imported_init_fns)
331 {
332   if (import_init_fn.empty() && imported_init_fns.empty()) return;
333 
334   // Maps a given init function to the its index in the exported "init" clause.
335   std::map<std::string, unsigned> init_idx;
336 
337   this->write_c_string("init");
338 
339   if (!import_init_fn.empty())
340     {
341       this->write_c_string(" ");
342       this->write_string(package_name);
343       this->write_c_string(" ");
344       this->write_string(import_init_fn);
345       init_idx[import_init_fn] = 0;
346     }
347 
348   if (imported_init_fns.empty())
349     {
350       this->write_c_string(";\n");
351       return;
352     }
353 
354   typedef std::map<int, std::vector<std::string> > level_map;
355   Init_graph init_graph;
356   level_map inits_at_level;
357 
358   // Walk through the set of import inits (already sorted by
359   // init fcn name) and write them out to the exports.
360   for (Import_init_set::const_iterator p = imported_init_fns.begin();
361        p != imported_init_fns.end();
362        ++p)
363     {
364       const Import_init* ii = *p;
365 
366       if (ii->init_name() == import_init_fn)
367 	continue;
368 
369       this->write_c_string(" ");
370       this->write_string(ii->package_name());
371       this->write_c_string(" ");
372       this->write_string(ii->init_name());
373 
374       // Populate init_idx.
375       go_assert(init_idx.find(ii->init_name()) == init_idx.end());
376       unsigned idx = init_idx.size();
377       init_idx[ii->init_name()] = idx;
378 
379       // If the init function has a non-negative priority value, this
380       // is an indication that it was referred to in an older version
381       // export data section (e.g. we read a legacy object
382       // file). Record such init fcns so that we can fix up the graph
383       // for them (handled later in this function).
384       if (ii->priority() > 0)
385 	{
386 	  level_map::iterator it = inits_at_level.find(ii->priority());
387 	  if (it == inits_at_level.end())
388 	    {
389 	      std::vector<std::string> l;
390 	      l.push_back(ii->init_name());
391 	      inits_at_level[ii->priority()] = l;
392 	    }
393 	  else
394 	    it->second.push_back(ii->init_name());
395 	}
396     }
397   this->write_c_string(";\n");
398 
399   // Create the init graph. Start by populating the graph with
400   // all the edges we inherited from imported packages.
401   populate_init_graph(&init_graph, imported_init_fns, init_idx);
402 
403   // Now add edges from the local init function to each of the
404   // imported fcns.
405   if (!import_init_fn.empty())
406     {
407       unsigned src = 0;
408       go_assert(init_idx[import_init_fn] == 0);
409       for (Import_init_set::const_iterator p = imported_init_fns.begin();
410            p != imported_init_fns.end();
411            ++p)
412 	{
413           const Import_init* ii = *p;
414 	  unsigned sink = init_idx[ii->init_name()];
415 	  add_init_graph_edge(&init_graph, src, sink);
416 	}
417     }
418 
419   // In the scenario where one or more of the packages we imported
420   // was written with the legacy export data format, add dummy edges
421   // to capture the priority relationships. Here is a package import
422   // graph as an example:
423   //
424   //       *A
425   //       /|
426   //      / |
427   //     B  *C
428   //       /|
429   //      / |
430   //    *D *E
431   //     | /|
432   //     |/ |
433   //    *F  *G
434   //
435   // Let's suppose that the object for package "C" is from an old
436   // gccgo, e.g. it has the old export data format. All other
437   // packages are compiled with the new compiler and have the new
438   // format. Packages with *'s have init functions. The scenario is
439   // that we're compiling a package "A"; during this process we'll
440   // read the export data for "C". It should look something like
441   //
442   //   init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
443   //
444   // To capture this information and convey it to the consumers of
445   // "A", the code below adds edges to the graph from each priority K
446   // function to every priority K-1 function for appropriate values
447   // of K. This will potentially add more edges than we need (for
448   // example, an edge from D to G), but given that we don't expect
449   // to see large numbers of old objects, this will hopefully be OK.
450 
451   if (inits_at_level.size() > 0)
452     {
453       for (level_map::reverse_iterator it = inits_at_level.rbegin();
454            it != inits_at_level.rend(); ++it)
455 	{
456 	  int level = it->first;
457 	  if (level < 2) break;
458 	  const std::vector<std::string>& fcns_at_level = it->second;
459 	  for (std::vector<std::string>::const_iterator sit =
460 	           fcns_at_level.begin();
461 	       sit != fcns_at_level.end(); ++sit)
462 	    {
463 	      unsigned src = init_idx[*sit];
464 	      level_map::iterator it2 = inits_at_level.find(level - 1);
465 	      if (it2 != inits_at_level.end())
466 		{
467 		  const std::vector<std::string> fcns_at_lm1 = it2->second;
468 		  for (std::vector<std::string>::const_iterator mit =
469 		           fcns_at_lm1.begin();
470 		       mit != fcns_at_lm1.end(); ++mit)
471 		    {
472 		      unsigned sink = init_idx[*mit];
473 		      add_init_graph_edge(&init_graph, src, sink);
474 		    }
475 		}
476 	    }
477 	}
478     }
479 
480   // Write out the resulting graph.
481   this->write_c_string("init_graph");
482   for (Init_graph::const_iterator ki = init_graph.begin();
483        ki != init_graph.end(); ++ki)
484     {
485       unsigned src = ki->first;
486       const std::set<unsigned>& successors = ki->second;
487       for (std::set<unsigned>::const_iterator vi = successors.begin();
488            vi != successors.end(); ++vi)
489 	{
490 	  this->write_c_string(" ");
491 	  this->write_unsigned(src);
492 	  unsigned sink = (*vi);
493 	  this->write_c_string(" ");
494 	  this->write_unsigned(sink);
495 	}
496     }
497   this->write_c_string(";\n");
498 }
499 
500 // Write a name to the export stream.
501 
502 void
write_name(const std::string & name)503 Export::write_name(const std::string& name)
504 {
505   if (name.empty())
506     this->write_c_string("?");
507   else
508     this->write_string(Gogo::message_name(name));
509 }
510 
511 // Write an integer value to the export stream.
512 
513 void
write_int(int value)514 Export::write_int(int value)
515 {
516   char buf[100];
517   snprintf(buf, sizeof buf, "%d", value);
518   this->write_c_string(buf);
519 }
520 
521 // Write an integer value to the export stream.
522 
523 void
write_unsigned(unsigned value)524 Export::write_unsigned(unsigned value)
525 {
526   char buf[100];
527   snprintf(buf, sizeof buf, "%u", value);
528   this->write_c_string(buf);
529 }
530 
531 // Export a type.  We have to ensure that on import we create a single
532 // Named_type node for each named type.  We do this by keeping a hash
533 // table mapping named types to reference numbers.  The first time we
534 // see a named type we assign it a reference number by making an entry
535 // in the hash table.  If we see it again, we just refer to the
536 // reference number.
537 
538 // Named types are, of course, associated with packages.  Note that we
539 // may see a named type when importing one package, and then later see
540 // the same named type when importing a different package.  The home
541 // package may or may not be imported during this compilation.  The
542 // reference number scheme has to get this all right.  Basic approach
543 // taken from "On the Linearization of Graphs and Writing Symbol
544 // Files" by Robert Griesemer.
545 
546 void
write_type(const Type * type)547 Export::write_type(const Type* type)
548 {
549   // We don't want to assign a reference number to a forward
550   // declaration to a type which was defined later.
551   type = type->forwarded();
552 
553   Type_refs::const_iterator p = this->type_refs_.find(type);
554   if (p != this->type_refs_.end())
555     {
556       // This type was already in the table.
557       int index = p->second;
558       go_assert(index != 0);
559       char buf[30];
560       snprintf(buf, sizeof buf, "<type %d>", index);
561       this->write_c_string(buf);
562       return;
563     }
564 
565   const Named_type* named_type = type->named_type();
566   const Forward_declaration_type* forward = type->forward_declaration_type();
567 
568   int index = this->type_index_;
569   ++this->type_index_;
570 
571   char buf[30];
572   snprintf(buf, sizeof buf, "<type %d ", index);
573   this->write_c_string(buf);
574 
575   if (named_type != NULL || forward != NULL)
576     {
577       const Named_object* named_object;
578       if (named_type != NULL)
579 	{
580 	  // The builtin types should have been predefined.
581 	  go_assert(!Linemap::is_predeclared_location(named_type->location())
582 		     || (named_type->named_object()->package()->package_name()
583 			 == "unsafe"));
584 	  named_object = named_type->named_object();
585 	}
586       else
587 	named_object = forward->named_object();
588 
589       const Package* package = named_object->package();
590 
591       std::string s = "\"";
592       if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
593 	{
594 	  s += package->pkgpath();
595 	  s += '.';
596 	}
597       s += named_object->name();
598       s += "\" ";
599       this->write_string(s);
600 
601       // It is possible that this type was imported indirectly, and is
602       // not in a package in the import list.  If we have not
603       // mentioned this package before, write out the package name
604       // here so that any package importing this one will know it.
605       if (package != NULL
606 	  && this->packages_.find(package) == this->packages_.end())
607 	{
608 	  this->write_c_string("\"");
609 	  this->write_string(package->package_name());
610 	  this->packages_.insert(package);
611 	  this->write_c_string("\" ");
612 	}
613 
614       // We must add a named type to the table now, since the
615       // definition of the type may refer to the named type via a
616       // pointer.
617       this->type_refs_[type] = index;
618 
619       if (named_type != NULL && named_type->is_alias())
620 	this->write_c_string("= ");
621     }
622 
623   type->export_type(this);
624 
625   this->write_c_string(">");
626 
627   if (named_type == NULL)
628     this->type_refs_[type] = index;
629 }
630 
631 // Export escape note.
632 
633 void
write_escape(std::string * note)634 Export::write_escape(std::string* note)
635 {
636   if (note != NULL && *note != "esc:0x0")
637     {
638       this->write_c_string(" ");
639       char buf[50];
640       go_assert(note->find("esc:") != std::string::npos);
641       snprintf(buf, sizeof buf, "<%s>", note->c_str());
642       this->write_c_string(buf);
643     }
644 }
645 
646 // Add the builtin types to the export table.
647 
648 void
register_builtin_types(Gogo * gogo)649 Export::register_builtin_types(Gogo* gogo)
650 {
651   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
652   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
653   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
654   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
655   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
656   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
657   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
658   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
659   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
660   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
661   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
662   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
663   this->register_builtin_type(gogo, "int", BUILTIN_INT);
664   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
665   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
666   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
667   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
668   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
669   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
670   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
671 }
672 
673 // Register one builtin type in the export table.
674 
675 void
register_builtin_type(Gogo * gogo,const char * name,Builtin_code code)676 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
677 {
678   Named_object* named_object = gogo->lookup_global(name);
679   go_assert(named_object != NULL && named_object->is_type());
680   std::pair<Type_refs::iterator, bool> ins =
681     this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
682   go_assert(ins.second);
683 
684   // We also insert the underlying type.  We can see the underlying
685   // type at least for string and bool.  We skip the type aliases byte
686   // and rune here.
687   if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
688     {
689       Type* real_type = named_object->type_value()->real_type();
690       ins = this->type_refs_.insert(std::make_pair(real_type, code));
691       go_assert(ins.second);
692     }
693 }
694 
695 // Class Export::Stream.
696 
Stream()697 Export::Stream::Stream()
698 {
699   this->sha1_helper_ = go_create_sha1_helper();
700   go_assert(this->sha1_helper_ != NULL);
701 }
702 
~Stream()703 Export::Stream::~Stream()
704 {
705 }
706 
707 // Write bytes to the stream.  This keeps a checksum of bytes as they
708 // go by.
709 
710 void
write_and_sum_bytes(const char * bytes,size_t length)711 Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
712 {
713   this->sha1_helper_->process_bytes(bytes, length);
714   this->do_write(bytes, length);
715 }
716 
717 // Get the checksum.
718 
719 std::string
checksum()720 Export::Stream::checksum()
721 {
722   std::string rval = this->sha1_helper_->finish();
723   delete this->sha1_helper_;
724   return rval;
725 }
726 
727 // Write the checksum string to the export data.
728 
729 void
write_checksum(const std::string & s)730 Export::Stream::write_checksum(const std::string& s)
731 {
732   this->do_write(s.data(), s.length());
733 }
734 
735 // Class Stream_to_section.
736 
Stream_to_section(Backend * backend)737 Stream_to_section::Stream_to_section(Backend* backend)
738     : backend_(backend)
739 {
740 }
741 
742 // Write data to a section.
743 
744 void
do_write(const char * bytes,size_t length)745 Stream_to_section::do_write(const char* bytes, size_t length)
746 {
747   this->backend_->write_export_data (bytes, length);
748 }
749