Пример #1
0
void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const {
  bool first = true;
  s << "{";
  if (pretty_print) {
    s << "\n";
    s.IndentMore();
  }
  for (const auto &pair : m_dict) {
    if (first)
      first = false;
    else {
      s << ",";
      if (pretty_print)
        s << "\n";
    }
    if (pretty_print)
      s.Indent();
    s << "\"" << pair.first.AsCString() << "\" : ";
    pair.second->Dump(s, pretty_print);
  }
  if (pretty_print) {
    s.IndentLess();
    s.EOL();
    s.Indent();
  }
  s << "}";
}
Пример #2
0
void StructuredData::Array::Dump(Stream &s, bool pretty_print) const {
  bool first = true;
  s << "[";
  if (pretty_print) {
    s << "\n";
    s.IndentMore();
  }
  for (const auto &item_sp : m_items) {
    if (first) {
      first = false;
    } else {
      s << ",";
      if (pretty_print)
        s << "\n";
    }

    if (pretty_print)
      s.Indent();
    item_sp->Dump(s, pretty_print);
  }
  if (pretty_print) {
    s.IndentLess();
    s.EOL();
    s.Indent();
  }
  s << "]";
}
Пример #3
0
size_t
StackFrameList::GetStatus (Stream& strm,
                           uint32_t first_frame,
                           uint32_t num_frames,
                           bool show_frame_info,
                           uint32_t num_frames_with_source,
                           const char *selected_frame_marker)
{
    size_t num_frames_displayed = 0;
    
    if (num_frames == 0)
        return 0;
    
    StackFrameSP frame_sp;
    uint32_t frame_idx = 0;
    uint32_t last_frame;
    
    // Don't let the last frame wrap around...
    if (num_frames == UINT32_MAX)
        last_frame = UINT32_MAX;
    else
        last_frame = first_frame + num_frames;
    
    StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame();
    const char *unselected_marker = NULL;
    std::string buffer;
    if (selected_frame_marker)
    {
        size_t len = strlen(selected_frame_marker);
        buffer.insert(buffer.begin(), len, ' ');
        unselected_marker = buffer.c_str();
    }
    const char *marker = NULL;
    
    for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
    {
        frame_sp = GetFrameAtIndex(frame_idx);
        if (frame_sp.get() == NULL)
            break;
        
        if (selected_frame_marker != NULL)
        {
            if (frame_sp == selected_frame_sp)
                marker = selected_frame_marker;
            else
                marker = unselected_marker;
        }
        
        if (!frame_sp->GetStatus (strm,
                                  show_frame_info,
                                  num_frames_with_source > (first_frame - frame_idx), marker))
            break;
        ++num_frames_displayed;
    }
    
    strm.IndentLess();
    return num_frames_displayed;
}
Пример #4
0
void
OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
    const Type dict_type = ConvertTypeMaskToType (m_type_mask);
    if (dump_mask & eDumpOptionType)
    {
        if (m_type_mask != eTypeInvalid)
            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type));
        else
            strm.Printf ("(%s)", GetTypeAsCString());
    }
    if (dump_mask & eDumpOptionValue)
    {
        if (dump_mask & eDumpOptionType)
            strm.PutCString (" =");

        collection::iterator pos, end = m_values.end();

        strm.IndentMore();
        
        for (pos = m_values.begin(); pos != end; ++pos)
        {
            OptionValue *option_value = pos->second.get();
            strm.EOL();
            strm.Indent(pos->first.GetCString());
            
            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
            switch (dict_type)
            {
                default:
                case eTypeArray:
                case eTypeDictionary:
                case eTypeProperties:
                case eTypeFileSpecList:
                case eTypePathMap:
                    strm.PutChar (' ');
                    option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
                    break;

                case eTypeBoolean:
                case eTypeChar:
                case eTypeEnum:
                case eTypeFileSpec:
                case eTypeFormat:
                case eTypeSInt64:
                case eTypeString:
                case eTypeUInt64:
                case eTypeUUID:
                    // No need to show the type for dictionaries of simple items
                    strm.PutCString("=");
                    option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
                    break;
            }
        }
        strm.IndentLess();
    }

}
Пример #5
0
void
OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
    const Type array_element_type = ConvertTypeMaskToType (m_type_mask);
    if (dump_mask & eDumpOptionType)
    {
        if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type));
        else
            strm.Printf ("(%s)", GetTypeAsCString());
    }
    if (dump_mask & eDumpOptionValue)
    {
        if (dump_mask & eDumpOptionType)
            strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : "");
        strm.IndentMore();
        const uint32_t size = m_values.size();
        for (uint32_t i = 0; i<size; ++i)
        {
            strm.Indent();
            strm.Printf("[%u]: ", i);
            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
            switch (array_element_type)
            {
                default:
                case eTypeArray:
                case eTypeDictionary:
                case eTypeProperties:
                case eTypeFileSpecList:
                case eTypePathMap:
                    m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
                    break;
                    
                case eTypeBoolean:
                case eTypeChar:
                case eTypeEnum:
                case eTypeFileSpec:
                case eTypeFormat:
                case eTypeSInt64:
                case eTypeString:
                case eTypeUInt64:
                case eTypeUUID:
                    // No need to show the type for dictionaries of simple items
                    m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
                    break;
            }
            if (i < (size - 1))
                strm.EOL();
        }
        strm.IndentLess();
    }
}
Пример #6
0
size_t
Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint32_t num_frames_with_source)
{
    ExecutionContext exe_ctx (shared_from_this());
    Target *target = exe_ctx.GetTargetPtr();
    Process *process = exe_ctx.GetProcessPtr();
    size_t num_frames_shown = 0;
    strm.Indent();
    bool is_selected = false;
    if (process)
    {
        if (process->GetThreadList().GetSelectedThread().get() == this)
            is_selected = true;
    }
    strm.Printf("%c ", is_selected ? '*' : ' ');
    if (target && target->GetDebugger().GetUseExternalEditor())
    {
        StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
        if (frame_sp)
        {
            SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
            if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file)
            {
                Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
            }
        }
    }

    DumpUsingSettingsFormat (strm, start_frame);

    if (num_frames > 0)
    {
        strm.IndentMore();

        const bool show_frame_info = true;
        strm.IndentMore ();
        num_frames_shown = GetStackFrameList ()->GetStatus (strm,
                           start_frame,
                           num_frames,
                           show_frame_info,
                           num_frames_with_source);
        strm.IndentLess();
        strm.IndentLess();
    }
    return num_frames_shown;
}
Пример #7
0
void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
                                        Stream &strm, uint32_t dump_mask) {
  if (dump_mask & eDumpOptionType)
    strm.Printf("(%s)", GetTypeAsCString());
  if (dump_mask & eDumpOptionValue) {
    if (dump_mask & eDumpOptionType)
      strm.Printf(" =%s", m_current_value.GetSize() > 0 ? "\n" : "");
    strm.IndentMore();
    const uint32_t size = m_current_value.GetSize();
    for (uint32_t i = 0; i < size; ++i) {
      strm.Indent();
      strm.Printf("[%u]: ", i);
      m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
    }
    strm.IndentLess();
  }
}
    bool
    DumpRegisterSet (const ExecutionContext &exe_ctx,
                     Stream &strm,
                     RegisterContext *reg_ctx,
                     size_t set_idx,
                     bool primitive_only=false)
    {
        uint32_t unavailable_count = 0;
        uint32_t available_count = 0;

        if (!reg_ctx)
            return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...)

        const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
        if (reg_set)
        {
            strm.Printf ("%s:\n", reg_set->name);
            strm.IndentMore ();
            const size_t num_registers = reg_set->num_registers;
            for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
            {
                const uint32_t reg = reg_set->registers[reg_idx];
                const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
                // Skip the dumping of derived register if primitive_only is true.
                if (primitive_only && reg_info && reg_info->value_regs)
                    continue;

                if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
                    ++available_count;
                else
                    ++unavailable_count;
            }
            strm.IndentLess ();
            if (unavailable_count)
            {
                strm.Indent ();
                strm.Printf("%u registers were unavailable.\n", unavailable_count);
            }
            strm.EOL();
        }
        return available_count > 0;
    }
Пример #9
0
void
StructuredData::Dictionary::Dump (Stream &s) const
{
    bool first = true;
    s << "{\n";
    s.IndentMore();
    for (const auto &pair : m_dict)
    {
        if (first)
            first = false;
        else
            s << ",\n";
        s.Indent();
        s << "\"" << pair.first.AsCString() << "\" : ";
        pair.second->Dump(s);
    }
    s.IndentLess();
    s.EOL();
    s.Indent();
    s << "}";
}
Пример #10
0
void
StructuredData::Array::Dump(Stream &s) const
{
    bool first = true;
    s << "[\n";
    s.IndentMore();
    for (const auto &item_sp : m_items)
    {
        if (first)
            first = false;
        else
            s << ",\n";

        s.Indent();
        item_sp->Dump(s);
    }
    s.IndentLess();
    s.EOL();
    s.Indent();
    s << "]";
}
Пример #11
0
//----------------------------------------------------------------------
// DumpCallback
//
// A callback function for the static DWARFDebugInfo::Parse() function
// that gets called each time a compile unit header or debug information
// entry is successfully parsed.
//
// This function dump DWARF information and obey recurse depth and
// whether a single DIE is to be dumped (or all of the data).
//----------------------------------------------------------------------
static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data,
                                DWARFCompileUnit *cu, DWARFDebugInfoEntry *die,
                                const dw_offset_t next_offset,
                                const uint32_t curr_depth, void *userData) {
  DumpInfo *dumpInfo = (DumpInfo *)userData;
  Stream *s = dumpInfo->strm;
  bool show_parents =
      s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);

  if (die) {
    // Are we dumping everything?
    if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
      // Yes we are dumping everything. Obey our recurse level though
      if (curr_depth < dumpInfo->recurse_depth)
        die->Dump(dwarf2Data, cu, *s, 0);
    } else {
      // We are dumping a specific DIE entry by offset
      if (dumpInfo->die_offset == die->GetOffset()) {
        // We found the DIE we were looking for, dump it!
        if (show_parents) {
          s->SetIndentLevel(0);
          const uint32_t num_ancestors = dumpInfo->ancestors.size();
          if (num_ancestors > 0) {
            for (uint32_t i = 0; i < num_ancestors - 1; ++i) {
              dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
              s->IndentMore();
            }
          }
        }

        dumpInfo->found_depth = curr_depth;

        die->Dump(dwarf2Data, cu, *s, 0);

        // Note that we found the DIE we were looking for
        dumpInfo->found_die = true;

        // Since we are dumping a single DIE, if there are no children we are
        // done!
        if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
          return DW_INVALID_OFFSET; // Return an invalid address to end parsing
      } else if (dumpInfo->found_die) {
        // Are we done with all the children?
        if (curr_depth <= dumpInfo->found_depth)
          return DW_INVALID_OFFSET;

        // We have already found our DIE and are printing it's children. Obey
        // our recurse depth and return an invalid offset if we get done
        // dumping all of the children
        if (dumpInfo->recurse_depth == UINT32_MAX ||
            curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
          die->Dump(dwarf2Data, cu, *s, 0);
      } else if (dumpInfo->die_offset > die->GetOffset()) {
        if (show_parents)
          dumpInfo->ancestors.back() = *die;
      }
    }

    // Keep up with our indent level
    if (die->IsNULL()) {
      if (show_parents)
        dumpInfo->ancestors.pop_back();

      if (curr_depth <= 1)
        return cu->GetNextCompileUnitOffset();
      else
        s->IndentLess();
    } else if (die->HasChildren()) {
      if (show_parents) {
        DWARFDebugInfoEntry null_die;
        dumpInfo->ancestors.push_back(null_die);
      }
      s->IndentMore();
    }
  } else {
    if (cu == NULL)
      s->PutCString("NULL - cu");
    // We have a compile unit, reset our indent level to zero just in case
    s->SetIndentLevel(0);

    // See if we are dumping everything?
    if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
      // We are dumping everything
      if (cu) {
        cu->Dump(s);
        return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this
                                        // Compile Unit
      } else {
        return DW_INVALID_OFFSET;
      }
    } else {
      if (show_parents) {
        dumpInfo->ancestors.clear();
        dumpInfo->ancestors.resize(1);
      }

      // We are dumping only a single DIE possibly with it's children and
      // we must find it's compile unit before we can dump it properly
      if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) {
        // Not found, maybe the DIE offset provided wasn't correct?
        //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << "
        //  was not found." << endl;
        return DW_INVALID_OFFSET;
      } else {
        // See if the DIE is in this compile unit?
        if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) {
          return next_offset;
          //  // We found our compile unit that contains our DIE, just skip to
          //  dumping the requested DIE...
          //  return dumpInfo->die_offset;
        } else {
          // Skip to the next compile unit as the DIE isn't in the current one!
          if (cu) {
            return cu->GetNextCompileUnitOffset();
          } else {
            return DW_INVALID_OFFSET;
          }
        }
      }
    }
  }

  // Just return the current offset to parse the next CU or DIE entry
  return next_offset;
}
Пример #12
0
void
CommandInterpreter::OutputFormattedHelpText (Stream &strm,
                                             const char *word_text,
                                             const char *separator,
                                             const char *help_text,
                                             uint32_t max_word_len)
{
    StateVariable *var = GetStateVariable ("term-width");
    int max_columns = var->GetIntValue();
    // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb
    // (0 rows; 0 columns;).
    if (max_columns <= 0) max_columns = 80;
    
    int indent_size = max_word_len + strlen (separator) + 2;

    strm.IndentMore (indent_size);

    int len = indent_size + strlen (help_text) + 1;
    char *text  = (char *) malloc (len);
    sprintf (text, "%-*s %s %s",  max_word_len, word_text, separator, help_text);
    if (text[len - 1] == '\n')
        text[--len] = '\0';

    if (len  < max_columns)
    {
        // Output it as a single line.
        strm.Printf ("%s", text);
    }
    else
    {
        // We need to break it up into multiple lines.
        bool first_line = true;
        int text_width;
        int start = 0;
        int end = start;
        int final_end = strlen (text);
        int sub_len;
        
        while (end < final_end)
        {
            if (first_line)
                text_width = max_columns - 1;
            else
                text_width = max_columns - indent_size - 1;

            // Don't start the 'text' on a space, since we're already outputting the indentation.
            if (!first_line)
            {
                while ((start < final_end) && (text[start] == ' '))
                  start++;
            }

            end = start + text_width;
            if (end > final_end)
                end = final_end;
            else
            {
                // If we're not at the end of the text, make sure we break the line on white space.
                while (end > start
                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
                    end--;
            }

            sub_len = end - start;
            if (start != 0)
              strm.EOL();
            if (!first_line)
                strm.Indent();
            else
                first_line = false;
            assert (start <= final_end);
            assert (start + sub_len <= final_end);
            if (sub_len > 0)
                strm.Write (text + start, sub_len);
            start = end + 1;
        }
    }
    strm.EOL();
    strm.IndentLess(indent_size);
    free (text);
}
Пример #13
0
void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
                                  uint32_t screen_width) {
  const bool only_print_args = cmd->IsDashDashCommand();

  auto opt_defs = GetDefinitions();
  const uint32_t save_indent_level = strm.GetIndentLevel();
  llvm::StringRef name;

  StreamString arguments_str;

  if (cmd) {
    name = cmd->GetCommandName();
    cmd->GetFormattedCommandArguments(arguments_str);
  } else
    name = "";

  strm.PutCString("\nCommand Options Usage:\n");

  strm.IndentMore(2);

  // First, show each usage level set of options, e.g. <cmd>
  // [options-for-level-0]
  //                                                   <cmd>
  //                                                   [options-for-level-1]
  //                                                   etc.

  const uint32_t num_options = NumCommandOptions();
  if (num_options == 0)
    return;

  uint32_t num_option_sets = GetRequiredOptions().size();

  uint32_t i;

  if (!only_print_args) {
    for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) {
      uint32_t opt_set_mask;

      opt_set_mask = 1 << opt_set;
      if (opt_set > 0)
        strm.Printf("\n");
      strm.Indent(name);

      // Different option sets may require different args.
      StreamString args_str;
      if (cmd)
        cmd->GetFormattedCommandArguments(args_str, opt_set_mask);

      // First go through and print all options that take no arguments as
      // a single string. If a command has "-a" "-b" and "-c", this will show
      // up as [-abc]

      std::set<int> options;
      std::set<int>::const_iterator options_pos, options_end;
      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) {
          // Add current option to the end of out_stream.

          if (def.required && def.option_has_arg == OptionParser::eNoArgument) {
            options.insert(def.short_option);
          }
        }
      }

      if (options.empty() == false) {
        // We have some required options with no arguments
        strm.PutCString(" -");
        for (i = 0; i < 2; ++i)
          for (options_pos = options.begin(), options_end = options.end();
               options_pos != options_end; ++options_pos) {
            if (i == 0 && ::islower(*options_pos))
              continue;
            if (i == 1 && ::isupper(*options_pos))
              continue;
            strm << (char)*options_pos;
          }
      }

      options.clear();
      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) {
          // Add current option to the end of out_stream.

          if (def.required == false &&
              def.option_has_arg == OptionParser::eNoArgument) {
            options.insert(def.short_option);
          }
        }
      }

      if (options.empty() == false) {
        // We have some required options with no arguments
        strm.PutCString(" [-");
        for (i = 0; i < 2; ++i)
          for (options_pos = options.begin(), options_end = options.end();
               options_pos != options_end; ++options_pos) {
            if (i == 0 && ::islower(*options_pos))
              continue;
            if (i == 1 && ::isupper(*options_pos))
              continue;
            strm << (char)*options_pos;
          }
        strm.PutChar(']');
      }

      // First go through and print the required options (list them up front).

      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) {
          if (def.required && def.option_has_arg != OptionParser::eNoArgument)
            PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
        }
      }

      // Now go through again, and this time only print the optional options.

      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask) {
          // Add current option to the end of out_stream.

          if (!def.required && def.option_has_arg != OptionParser::eNoArgument)
            PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
        }
      }

      if (args_str.GetSize() > 0) {
        if (cmd->WantsRawCommandString() && !only_print_args)
          strm.Printf(" --");

        strm << " " << args_str.GetString();
        if (only_print_args)
          break;
      }
    }
  }

  if (cmd && (only_print_args || cmd->WantsRawCommandString()) &&
      arguments_str.GetSize() > 0) {
    if (!only_print_args)
      strm.PutChar('\n');
    strm.Indent(name);
    strm << " " << arguments_str.GetString();
  }

  strm.Printf("\n\n");

  if (!only_print_args) {
    // Now print out all the detailed information about the various options:
    // long form, short form and help text:
    //   -short <argument> ( --long_name <argument> )
    //   help text

    // This variable is used to keep track of which options' info we've printed
    // out, because some options can be in
    // more than one usage level, but we only want to print the long form of its
    // information once.

    std::multimap<int, uint32_t> options_seen;
    strm.IndentMore(5);

    // Put the unique command options in a vector & sort it, so we can output
    // them alphabetically (by short_option)
    // when writing out detailed help for each option.

    i = 0;
    for (auto &def : opt_defs)
      options_seen.insert(std::make_pair(def.short_option, i++));

    // Go through the unique'd and alphabetically sorted vector of options, find
    // the table entry for each option
    // and write out the detailed help information for that option.

    bool first_option_printed = false;

    for (auto pos : options_seen) {
      i = pos.second;
      // Print out the help information for this option.

      // Put a newline separation between arguments
      if (first_option_printed)
        strm.EOL();
      else
        first_option_printed = true;

      CommandArgumentType arg_type = opt_defs[i].argument_type;

      StreamString arg_name_str;
      arg_name_str.Printf("<%s>", CommandObject::GetArgumentName(arg_type));

      strm.Indent();
      if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) {
        PrintOption(opt_defs[i], eDisplayShortOption, nullptr, nullptr, false,
                    strm);
        PrintOption(opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
      } else {
        // Short option is not printable, just print long option
        PrintOption(opt_defs[i], eDisplayLongOption, nullptr, nullptr, false,
                    strm);
      }
      strm.EOL();

      strm.IndentMore(5);

      if (opt_defs[i].usage_text)
        OutputFormattedUsageText(strm, opt_defs[i], screen_width);
      if (opt_defs[i].enum_values != nullptr) {
        strm.Indent();
        strm.Printf("Values: ");
        for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr;
             k++) {
          if (k == 0)
            strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
          else
            strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
        }
        strm.EOL();
      }
      strm.IndentLess(5);
    }
  }

  // Restore the indent level
  strm.SetIndentLevel(save_indent_level);
}
Пример #14
0
bool
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    const AddressRange &disasm_range,
    uint32_t num_mixed_context_lines,
    bool show_bytes,
    Stream &strm
)
{
    if (disasm_range.GetByteSize())
    {
        Disassembler *disassembler = Disassembler::FindPlugin(arch);

        if (disassembler)
        {
            AddressRange range(disasm_range);
            
            Process *process = exe_ctx.process;

            // If we weren't passed in a section offset address range,
            // try and resolve it to something
            if (range.GetBaseAddress().IsSectionOffset() == false)
            {
                if (process && process->IsAlive())
                {
                    process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
                }
                else if (exe_ctx.target)
                {
                    exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
                }
            }


            DataExtractor data;
            size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data);
            if (bytes_disassembled == 0)
            {
                return false;
            }
            else
            {
                // We got some things disassembled...
                size_t num_instructions = disassembler->GetInstructionList().GetSize();
                uint32_t offset = 0;
                SymbolContext sc;
                SymbolContext prev_sc;
                AddressRange sc_range;
                if (num_mixed_context_lines)
                    strm.IndentMore ();


                Address addr(range.GetBaseAddress());
    
                // We extract the section to make sure we don't transition out
                // of the current section when disassembling
                const Section *addr_section = addr.GetSection();
                Module *range_module = range.GetBaseAddress().GetModule();

                for (size_t i=0; i<num_instructions; ++i)
                {
                    Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
                    if (inst)
                    {
                        addr_t file_addr = addr.GetFileAddress();
                        if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
                        {
                            if (range_module)
                                range_module->ResolveFileAddress (file_addr, addr);
                            else if (exe_ctx.target)
                                exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
                                
                            addr_section = addr.GetSection();
                        }

                        prev_sc = sc;

                        if (addr_section)
                        {
                            Module *module = addr_section->GetModule();
                            uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                            if (resolved_mask)
                            {
                                if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol)
                                {
                                    if (prev_sc.function || prev_sc.symbol)
                                        strm.EOL();

                                    strm << sc.module_sp->GetFileSpec().GetFilename();
                                    
                                    if (sc.function)
                                        strm << '`' << sc.function->GetMangled().GetName();
                                    else if (sc.symbol)
                                        strm << '`' << sc.symbol->GetMangled().GetName();
                                    strm << ":\n";
                                }

                                if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
                                {
                                    sc.GetAddressRange (eSymbolContextEverything, sc_range);
                                        
                                    if (sc != prev_sc)
                                    {
                                        if (offset != 0)
                                            strm.EOL();

                                        sc.DumpStopContext(&strm, process, addr);

                                        if (sc.comp_unit && sc.line_entry.IsValid())
                                        {
                                            debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                                           sc.line_entry.line,
                                                                                                           num_mixed_context_lines,
                                                                                                           num_mixed_context_lines,
                                                                                                           num_mixed_context_lines ? "->" : "",
                                                                                                           &strm);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                sc.Clear();
                            }
                        }
                        if (num_mixed_context_lines)
                            strm.IndentMore ();
                        strm.Indent();
                        size_t inst_byte_size = inst->GetByteSize();
                        inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes);
                        strm.EOL();
                        offset += inst_byte_size;
                        
                        addr.SetOffset (addr.GetOffset() + inst_byte_size);

                        if (num_mixed_context_lines)
                            strm.IndentLess ();
                    }
                    else
                    {
                        break;
                    }
                }
                if (num_mixed_context_lines)
                    strm.IndentLess ();

            }
        }
        return true;
    }
    return false;
}