Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  dex_file-inl.h

  Sprache: C
 

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
#define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_

#include "dex_file.h"

#include "base/casts.h"
#include "base/iteration_range.h"
#include "base/leb128.h"
#include "base/utils.h"
#include "class_iterator.h"
#include "dex_instruction_iterator.h"
#include "invoke_type.h"
#include "signature.h"
#include "standard_dex_file.h"

namespace art {

inline int DexFile::CompareDescriptors(std::string_view lhs, std::string_view rhs) {
  // Note: `std::string_view::compare()` uses lexicographical comparison and treats the `char`
  // as unsigned; for Modified-UTF-8 without embedded nulls this is consistent with the
  // `CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues()` ordering.
  return lhs.compare(rhs);
}

inline int DexFile::CompareMemberNames(std::string_view lhs, std::string_view rhs) {
  // Note: `std::string_view::compare()` uses lexicographical comparison and treats the `char`
  // as unsigned; for Modified-UTF-8 without embedded nulls this is consistent with the
  // `CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues()` ordering.
  return lhs.compare(rhs);
}

inline size_t DexFile::Utf8Length(const char* utf8_data, size_t utf16_length) {
  return LIKELY(utf8_data[utf16_length] == 0)  // Is ASCII?
             ? utf16_length
             : utf16_length + strlen(utf8_data + utf16_length);
}

inline std::string_view DexFile::StringViewFromUtf16Length(const char* utf8_data,
                                                           size_t utf16_length) {
  return std::string_view(utf8_data, Utf8Length(utf8_data, utf16_length));
}

ALWAYS_INLINE
inline const char* DexFile::GetStringDataAndUtf16Length(const dex::StringId& string_id,
                                                        uint32_t* utf16_length) const {
  DCHECK(utf16_length != nullptr) << GetLocation();
  const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
  *utf16_length = DecodeUnsignedLeb128(&ptr);
  return reinterpret_cast<const char*>(ptr);
}

ALWAYS_INLINE
inline const char* DexFile::GetStringDataAndUtf16Length(const dex::StringIndex string_idx,
                                                        uint32_t* utf16_length) const {
  return GetStringDataAndUtf16Length(GetStringId(string_idx), utf16_length);
}

ALWAYS_INLINE
inline uint32_t DexFile::GetStringUtf16Length(const dex::StringId& string_id) const {
  uint32_t utf16_length;
  GetStringDataAndUtf16Length(string_id, &utf16_length);
  return utf16_length;
}

ALWAYS_INLINE
inline const char* DexFile::GetStringData(const dex::StringId& string_id) const {
  uint32_t ignored;
  return GetStringDataAndUtf16Length(string_id, &ignored);
}

ALWAYS_INLINE
inline const char* DexFile::GetStringData(dex::StringIndex string_idx) const {
  return GetStringData(GetStringId(string_idx));
}

ALWAYS_INLINE
inline std::string_view DexFile::GetStringView(const dex::StringId& string_id) const {
  uint32_t utf16_length;
  const char* data = GetStringDataAndUtf16Length(string_id, &utf16_length);
  return StringViewFromUtf16Length(data, utf16_length);
}

ALWAYS_INLINE
inline std::string_view DexFile::GetStringView(dex::StringIndex string_idx) const {
  return GetStringView(GetStringId(string_idx));
}

inline const char* DexFile::GetTypeDescriptor(const dex::TypeId& type_id) const {
  return GetStringData(type_id.descriptor_idx_);
}

inline const char* DexFile::GetTypeDescriptor(dex::TypeIndex type_idx) const {
  return GetTypeDescriptor(GetTypeId(type_idx));
}

inline std::string_view DexFile::GetTypeDescriptorView(const dex::TypeId& type_id) const {
  return GetStringView(type_id.descriptor_idx_);
}

inline std::string_view DexFile::GetTypeDescriptorView(dex::TypeIndex type_idx) const {
  return GetTypeDescriptorView(GetTypeId(type_idx));
}

inline const char* DexFile::GetFieldDeclaringClassDescriptor(const dex::FieldId& field_id) const {
  return GetTypeDescriptor(field_id.class_idx_);
}

inline const char* DexFile::GetFieldDeclaringClassDescriptor(uint32_t field_idx) const {
  return GetFieldDeclaringClassDescriptor(GetFieldId(field_idx));
}

inline std::string_view DexFile::GetFieldDeclaringClassDescriptorView(
    const dex::FieldId& field_id) const {
  return GetTypeDescriptorView(field_id.class_idx_);
}

inline std::string_view DexFile::GetFieldDeclaringClassDescriptorView(uint32_t field_idx) const {
  return GetFieldDeclaringClassDescriptorView(GetFieldId(field_idx));
}

inline const char* DexFile::GetFieldTypeDescriptor(const dex::FieldId& field_id) const {
  return GetTypeDescriptor(field_id.type_idx_);
}

inline const char* DexFile::GetFieldTypeDescriptor(uint32_t field_idx) const {
  return GetFieldTypeDescriptor(GetFieldId(field_idx));
}

inline std::string_view DexFile::GetFieldTypeDescriptorView(const dex::FieldId& field_id) const {
  return GetTypeDescriptorView(field_id.type_idx_);
}

inline std::string_view DexFile::GetFieldTypeDescriptorView(uint32_t field_idx) const {
  return GetFieldTypeDescriptorView(GetFieldId(field_idx));
}

inline const char* DexFile::GetFieldName(const dex::FieldId& field_id) const {
  return GetStringData(field_id.name_idx_);
}

inline const char* DexFile::GetFieldName(uint32_t field_idx) const {
  return GetFieldName(GetFieldId(field_idx));
}

inline std::string_view DexFile::GetFieldNameView(const dex::FieldId& field_id) const {
  return GetStringView(field_id.name_idx_);
}

inline std::string_view DexFile::GetFieldNameView(uint32_t field_idx) const {
  return GetFieldNameView(GetFieldId(field_idx));
}

inline const char* DexFile::GetMethodDeclaringClassDescriptor(
    const dex::MethodId& method_id) const {
  return GetTypeDescriptor(method_id.class_idx_);
}

inline const char* DexFile::GetMethodDeclaringClassDescriptor(uint32_t method_idx) const {
  return GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
}

inline std::string_view DexFile::GetMethodDeclaringClassDescriptorView(
    const dex::MethodId& method_id) const {
  return GetTypeDescriptorView(method_id.class_idx_);
}

inline std::string_view DexFile::GetMethodDeclaringClassDescriptorView(uint32_t method_idx) const {
  return GetMethodDeclaringClassDescriptorView(GetMethodId(method_idx));
}

inline const Signature DexFile::GetMethodSignature(const dex::MethodId& method_idconst {
  return Signature(this, GetProtoId(method_id.proto_idx_));
}

inline const Signature DexFile::GetProtoSignature(const dex::ProtoId& proto_id) const {
  return Signature(this, proto_id);
}

inline const char* DexFile::GetMethodName(const dex::MethodId& method_id) const {
  return GetStringData(method_id.name_idx_);
}

inline const char* DexFile::GetMethodName(const dex::MethodId& method_id, uint32_t* utf_length)
    const {
  return GetStringDataAndUtf16Length(method_id.name_idx_, utf_length);
}

inline const char* DexFile::GetMethodName(uint32_t method_idx) const {
  return GetStringData(GetMethodId(method_idx).name_idx_);
}

inline const char* DexFile::GetMethodName(uint32_t idx, uint32_t* utf_length) const {
  return GetStringDataAndUtf16Length(GetMethodId(idx).name_idx_, utf_length);
}

ALWAYS_INLINE
inline std::string_view DexFile::GetMethodNameView(const dex::MethodId& method_id) const {
  return GetStringView(method_id.name_idx_);
}

ALWAYS_INLINE
inline std::string_view DexFile::GetMethodNameView(uint32_t method_idx) const {
  return GetMethodNameView(GetMethodId(method_idx));
}

inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
  return GetMethodShorty(GetMethodId(idx));
}

inline std::string_view DexFile::GetMethodShortyView(uint32_t idx) const {
  return GetMethodShortyView(GetMethodId(idx));
}

inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id) const {
  return GetStringData(GetProtoId(method_id.proto_idx_).shorty_idx_);
}

inline const char* DexFile::GetMethodShorty(const dex::MethodId& method_id, uint32_t* length)
    const {
  // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters.
  return GetStringDataAndUtf16Length(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
}

inline std::string_view DexFile::GetMethodShortyView(const dex::MethodId& method_id) const {
  return GetShortyView(method_id.proto_idx_);
}

inline const char* DexFile::GetClassDescriptor(const dex::ClassDef& class_def) const {
  return GetTypeDescriptor(class_def.class_idx_);
}

inline const char* DexFile::GetReturnTypeDescriptor(const dex::ProtoId& proto_id) const {
  return GetTypeDescriptor(proto_id.return_type_idx_);
}

inline const char* DexFile::GetShorty(dex::ProtoIndex proto_idx) const {
  const dex::ProtoId& proto_id = GetProtoId(proto_idx);
  return GetStringData(proto_id.shorty_idx_);
}

ALWAYS_INLINE
inline std::string_view DexFile::GetShortyView(dex::ProtoIndex proto_idx) const {
  return GetShortyView(GetProtoId(proto_idx));
}

ALWAYS_INLINE
inline std::string_view DexFile::GetShortyView(const dex::ProtoId& proto_id) const {
  uint32_t shorty_len;
  const char* shorty_data = GetStringDataAndUtf16Length(proto_id.shorty_idx_, &shorty_len);
  DCHECK_EQ(shorty_data[shorty_len], '\0');  // For a shorty utf16 length == mutf8 length.
  return std::string_view(shorty_data, shorty_len);
}

inline const dex::TryItem* DexFile::GetTryItems(const DexInstructionIterator& code_item_end,
                                                uint32_t offset) {
  return reinterpret_cast<const dex::TryItem*>
      (RoundUp(reinterpret_cast<uintptr_t>(&code_item_end.Inst()), dex::TryItem::kAlignment)) +
          offset;
}

inline bool DexFile::StringEquals(const DexFile* df1, dex::StringIndex sidx1,
                                  const DexFile* df2, dex::StringIndex sidx2) {
  uint32_t s1_len;  // Note: utf16 length != mutf8 length.
  const char* s1_data = df1->GetStringDataAndUtf16Length(sidx1, &s1_len);
  uint32_t s2_len;
  const char* s2_data = df2->GetStringDataAndUtf16Length(sidx2, &s2_len);
  return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
}

template<typename NewLocalCallback, typename IndexToStringData, typename TypeIndexToStringData>
bool DexFile::DecodeDebugLocalInfo(const uint8_t* stream,
                                   const std::string& location,
                                   const char* declaring_class_descriptor,
                                   const std::vector<const char*>& arg_descriptors,
                                   const std::string& method_name,
                                   bool is_static,
                                   uint16_t registers_size,
                                   uint16_t ins_size,
                                   uint16_t insns_size_in_code_units,
                                   const IndexToStringData& index_to_string_data,
                                   const TypeIndexToStringData& type_index_to_string_data,
                                   const NewLocalCallback& new_local_callback) {
  if (stream == nullptr) {
    return false;
  }
  std::vector<LocalInfo> local_in_reg(registers_size);

  uint16_t arg_reg = registers_size - ins_size;
  if (!is_static) {
    const char* descriptor = declaring_class_descriptor;
    local_in_reg[arg_reg].name_ = "this";
    local_in_reg[arg_reg].descriptor_ = descriptor;
    local_in_reg[arg_reg].signature_ = nullptr;
    local_in_reg[arg_reg].start_address_ = 0;
    local_in_reg[arg_reg].reg_ = arg_reg;
    local_in_reg[arg_reg].is_live_ = true;
    arg_reg++;
  }

  DecodeUnsignedLeb128(&stream);  // Line.
  uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
  uint32_t i;
  if (parameters_size != arg_descriptors.size()) {
    LOG(ERROR) << "invalid stream - problem with parameter iterator in " << location
               << " for method " << method_name;
    return false;
  }
  for (i = 0; i < parameters_size && i < arg_descriptors.size(); ++i) {
    if (arg_reg >= registers_size) {
      LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
                 << " >= " << registers_size << ") in " << location;
      return false;
    }
    uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
    const char* descriptor = arg_descriptors[i];
    local_in_reg[arg_reg].name_ = index_to_string_data(name_idx);
    local_in_reg[arg_reg].descriptor_ = descriptor;
    local_in_reg[arg_reg].signature_ = nullptr;
    local_in_reg[arg_reg].start_address_ = 0;
    local_in_reg[arg_reg].reg_ = arg_reg;
    local_in_reg[arg_reg].is_live_ = true;
    switch (*descriptor) {
      case 'D':
      case 'J':
        arg_reg += 2;
        break;
      default:
        arg_reg += 1;
        break;
    }
  }

  uint32_t address = 0;
  for (;;)  {
    uint8_t opcode = *stream++;
    switch (opcode) {
      case DBG_END_SEQUENCE:
        // Emit all variables which are still alive at the end of the method.
        for (uint16_t reg = 0; reg < registers_size; reg++) {
          if (local_in_reg[reg].is_live_) {
            local_in_reg[reg].end_address_ = insns_size_in_code_units;
            new_local_callback(local_in_reg[reg]);
          }
        }
        return true;
      case DBG_ADVANCE_PC:
        address += DecodeUnsignedLeb128(&stream);
        break;
      case DBG_ADVANCE_LINE:
        DecodeSignedLeb128(&stream);  // Line.
        break;
      case DBG_START_LOCAL:
      case DBG_START_LOCAL_EXTENDED: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }

        uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
        uint16_t descriptor_idx = DecodeUnsignedLeb128P1(&stream);
        uint32_t signature_idx = dex::kDexNoIndex;
        if (opcode == DBG_START_LOCAL_EXTENDED) {
          signature_idx = DecodeUnsignedLeb128P1(&stream);
        }

        // Emit what was previously there, if anything
        if (local_in_reg[reg].is_live_) {
          local_in_reg[reg].end_address_ = address;
          // Parameters with generic types cannot be encoded in the debug_info_item header. So d8
          // encodes it as null in the header with start and end address as 0. There will be a
          // START_LOCAL_EXTENDED that will declare the parameter with correct signature
          // Debuggers get confused when they see empty ranges. So don't emit them.
          // See b/297843934 for more details.
          if (local_in_reg[reg].end_address_ != 0) {
            new_local_callback(local_in_reg[reg]);
          }
        }

        local_in_reg[reg].name_ = index_to_string_data(name_idx);
        local_in_reg[reg].descriptor_ = type_index_to_string_data(descriptor_idx);
        local_in_reg[reg].signature_ = index_to_string_data(signature_idx);
        local_in_reg[reg].start_address_ = address;
        local_in_reg[reg].reg_ = reg;
        local_in_reg[reg].is_live_ = true;
        break;
      }
      case DBG_END_LOCAL: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }
        // If the register is live, close it properly. Otherwise, closing an already
        // closed register is sloppy, but harmless if no further action is taken.
        if (local_in_reg[reg].is_live_) {
          local_in_reg[reg].end_address_ = address;
          new_local_callback(local_in_reg[reg]);
          local_in_reg[reg].is_live_ = false;
        }
        break;
      }
      case DBG_RESTART_LOCAL: {
        uint16_t reg = DecodeUnsignedLeb128(&stream);
        if (reg >= registers_size) {
          LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
                     << registers_size << ") in " << location;
          return false;
        }
        // If the register is live, the "restart" is superfluous,
        // and we don't want to mess with the existing start address.
        if (!local_in_reg[reg].is_live_) {
          local_in_reg[reg].start_address_ = address;
          local_in_reg[reg].is_live_ = true;
        }
        break;
      }
      case DBG_SET_PROLOGUE_END:
      case DBG_SET_EPILOGUE_BEGIN:
        break;
      case DBG_SET_FILE:
        DecodeUnsignedLeb128P1(&stream);  // name.
        break;
      default:
        address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE;
        break;
    }
  }
}

template<typename NewLocalCallback>
bool DexFile::DecodeDebugLocalInfo(uint32_t registers_size,
                                   uint32_t ins_size,
                                   uint32_t insns_size_in_code_units,
                                   uint32_t debug_info_offset,
                                   bool is_static,
                                   uint32_t method_idx,
                                   const NewLocalCallback& new_local_callback) const {
  const uint8_t* const stream = GetDebugInfoStream(debug_info_offset);
  if (stream == nullptr) {
    return false;
  }
  std::vector<const char*> arg_descriptors;
  DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
  for (; it.HasNext(); it.Next()) {
    arg_descriptors.push_back(it.GetDescriptor());
  }
  return DecodeDebugLocalInfo(stream,
                              GetLocation(),
                              GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)),
                              arg_descriptors,
                              this->PrettyMethod(method_idx),
                              is_static,
                              registers_size,
                              ins_size,
                              insns_size_in_code_units,
                              [this](uint32_t idx) {
                                dex::StringIndex string_idx(idx);
                                return string_idx.IsValid() ? GetStringData(string_idx) : nullptr;
                              },
                              [this](uint16_t idx) {
                                dex::TypeIndex type_idx(idx);
                                return type_idx.IsValid() ? GetTypeDescriptor(type_idx) : nullptr;
                              },
                              new_local_callback);
}

template<typename DexDebugNewPosition, typename IndexToStringData>
bool DexFile::DecodeDebugPositionInfo(const uint8_t* stream,
                                      IndexToStringData&& index_to_string_data,
                                      DexDebugNewPosition&& position_functor) {
  if (stream == nullptr) {
    return false;
  }

  PositionInfo entry;
  entry.line_ = DecodeDebugInfoParameterNames(&stream, VoidFunctor());

  for (;;)  {
    uint8_t opcode = *stream++;
    switch (opcode) {
      case DBG_END_SEQUENCE:
        return true;  // end of stream.
      case DBG_ADVANCE_PC:
        entry.address_ += DecodeUnsignedLeb128(&stream);
        break;
      case DBG_ADVANCE_LINE:
        entry.line_ += DecodeSignedLeb128(&stream);
        break;
      case DBG_START_LOCAL:
        DecodeUnsignedLeb128(&stream);  // reg.
        DecodeUnsignedLeb128P1(&stream);  // name.
        DecodeUnsignedLeb128P1(&stream);  // descriptor.
        break;
      case DBG_START_LOCAL_EXTENDED:
        DecodeUnsignedLeb128(&stream);  // reg.
        DecodeUnsignedLeb128P1(&stream);  // name.
        DecodeUnsignedLeb128P1(&stream);  // descriptor.
        DecodeUnsignedLeb128P1(&stream);  // signature.
        break;
      case DBG_END_LOCAL:
      case DBG_RESTART_LOCAL:
        DecodeUnsignedLeb128(&stream);  // reg.
        break;
      case DBG_SET_PROLOGUE_END:
        entry.prologue_end_ = true;
        break;
      case DBG_SET_EPILOGUE_BEGIN:
        entry.epilogue_begin_ = true;
        break;
      case DBG_SET_FILE: {
        uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
        entry.source_file_ = index_to_string_data(name_idx);
        break;
      }
      default: {
        int adjopcode = opcode - DBG_FIRST_SPECIAL;
        entry.address_ += adjopcode / DBG_LINE_RANGE;
        entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
        if (position_functor(entry)) {
          return true;  // early exit.
        }
        entry.prologue_end_ = false;
        entry.epilogue_begin_ = false;
        break;
      }
    }
  }
}

inline const StandardDexFile* DexFile::AsStandardDexFile() const {
  return down_cast<const StandardDexFile*>(this);
}

// Get the base of the encoded data for the given DexCode.
inline const uint8_t* DexFile::GetCatchHandlerData(const DexInstructionIterator& code_item_end,
                                                   uint32_t tries_size,
                                                   uint32_t offset) {
  const uint8_t* handler_data =
      reinterpret_cast<const uint8_t*>(GetTryItems(code_item_end, tries_size));
  return handler_data + offset;
}

inline IterationRange<ClassIterator> DexFile::GetClasses() const {
  return { ClassIterator(*this0u), ClassIterator(*this, NumClassDefs()) };
}

// Returns the line number
template <typename Visitor>
inline uint32_t DexFile::DecodeDebugInfoParameterNames(const uint8_t** debug_info,
                                                       Visitor&& visitor) {
  uint32_t line = DecodeUnsignedLeb128(debug_info);
  const uint32_t parameters_size = DecodeUnsignedLeb128(debug_info);
  for (uint32_t i = 0; i < parameters_size; ++i) {
    visitor(dex::StringIndex(DecodeUnsignedLeb128P1(debug_info)));
  }
  return line;
}

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_

Messung V0.5 in Prozent
C=90 H=97 G=93

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik