- // If the ':' appeared in the directory name, compare to the end
- // of the string.
- if (s1end < s1begin)
- s1end = s1.size();
- if (s2end < s2begin)
- s2end = s2.size();
- // Compare takes lengths, not end indices.
- return s1.compare(s1begin, s1end - s1begin,
- s2, s2begin, s2end - s2begin) < 0;
+ return s1.compare(s1begin, std::string::npos,
+ s2, s2begin, std::string::npos) < 0;
+ }
+};
+
+// Returns all of the lines attached to LOC, not just the one the
+// instruction actually came from.
+std::vector<std::string>
+Symbol_table::linenos_from_loc(const Task* task,
+ const Symbol_location& loc)
+{
+ // We need to lock the object in order to read it. This
+ // means that we have to run in a singleton Task. If we
+ // want to run this in a general Task for better
+ // performance, we will need one Task for object, plus
+ // appropriate locking to ensure that we don't conflict with
+ // other uses of the object. Also note, one_addr2line is not
+ // currently thread-safe.
+ Task_lock_obj<Object> tl(task, loc.object);
+
+ std::vector<std::string> result;
+ Symbol_location code_loc = loc;
+ parameters->target().function_location(&code_loc);
+ // 16 is the size of the object-cache that one_addr2line should use.
+ std::string canonical_result = Dwarf_line_info::one_addr2line(
+ code_loc.object, code_loc.shndx, code_loc.offset, 16, &result);
+ if (!canonical_result.empty())
+ result.push_back(canonical_result);
+ return result;
+}
+
+// OutputIterator that records if it was ever assigned to. This
+// allows it to be used with std::set_intersection() to check for
+// intersection rather than computing the intersection.
+struct Check_intersection
+{
+ Check_intersection()
+ : value_(false)
+ {}
+
+ bool had_intersection() const
+ { return this->value_; }
+
+ Check_intersection& operator++()
+ { return *this; }
+
+ Check_intersection& operator*()
+ { return *this; }
+
+ template<typename T>
+ Check_intersection& operator=(const T&)
+ {
+ this->value_ = true;
+ return *this;