static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) { uint32_t clk_base; uint32_t clk_sel; uint32_t res; uint16_t clk; uint16_t div; int timeout; if (clock == slot->clock) return; slot->clock = clock; /* Turn off the clock. */ clk = RD2(slot, SDHCI_CLOCK_CONTROL); WR2(slot, SDHCI_CLOCK_CONTROL, clk & ~SDHCI_CLOCK_CARD_EN); /* If no clock requested - left it so. */ if (clock == 0) return; /* Determine the clock base frequency */ clk_base = slot->max_clk; if (slot->quirks & SDHCI_QUIRK_BCM577XX_400KHZ_CLKSRC) { clk_sel = RD2(slot, BCM577XX_HOST_CONTROL) & BCM577XX_CTRL_CLKSEL_MASK; /* Select clock source appropriate for the requested frequency. */ if ((clk_base / BCM577XX_DEFAULT_MAX_DIVIDER) > clock) { clk_base = BCM577XX_ALT_CLOCK_BASE; clk_sel |= (BCM577XX_CTRL_CLKSEL_64MHZ << BCM577XX_CTRL_CLKSEL_SHIFT); } else { clk_sel |= (BCM577XX_CTRL_CLKSEL_DEFAULT << BCM577XX_CTRL_CLKSEL_SHIFT); } WR2(slot, BCM577XX_HOST_CONTROL, clk_sel); } /* Recalculate timeout clock frequency based on the new sd clock. */ if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) slot->timeout_clk = slot->clock / 1000; if (slot->version < SDHCI_SPEC_300) { /* Looking for highest freq <= clock. */ res = clk_base; for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) { if (res <= clock) break; res >>= 1; } /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ div >>= 1; }
static void imx_watchdog(void *arg, u_int cmd, int *error) { struct imx_wdog_softc *sc; uint16_t reg; u_int timeout; sc = arg; mtx_lock(&sc->sc_mtx); if (cmd == 0) { if (bootverbose) device_printf(sc->sc_dev, "Can not be disabled.\n"); *error = EOPNOTSUPP; } else { timeout = (u_int)((1ULL << (cmd & WD_INTERVAL)) / 1000000000U); if (timeout > 1 && timeout < 128) { if (timeout != sc->sc_timeout) { sc->sc_timeout = timeout; reg = RD2(sc, WDOG_CR_REG); reg &= ~WDOG_CR_WT_MASK; reg |= (timeout << (WDOG_CR_WT_SHIFT + 1)) & WDOG_CR_WT_MASK; WR2(sc, WDOG_CR_REG, reg | WDOG_CR_WDE); } /* Refresh counter */ WR2(sc, WDOG_SR_REG, WDOG_SR_STEP1); WR2(sc, WDOG_SR_REG, WDOG_SR_STEP2); *error = 0; } } mtx_unlock(&sc->sc_mtx); }
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) { uint32_t res; uint16_t clk; uint16_t div; int timeout; if (clock == slot->clock) return; slot->clock = clock; /* Turn off the clock. */ clk = RD2(slot, SDHCI_CLOCK_CONTROL); WR2(slot, SDHCI_CLOCK_CONTROL, clk & ~SDHCI_CLOCK_CARD_EN); /* If no clock requested - left it so. */ if (clock == 0) return; /* Recalculate timeout clock frequency based on the new sd clock. */ if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) slot->timeout_clk = slot->clock / 1000; if (slot->version < SDHCI_SPEC_300) { /* Looking for highest freq <= clock. */ res = slot->max_clk; for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) { if (res <= clock) break; res >>= 1; } /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ div >>= 1; }
static void sdhci_dumpregs(struct sdhci_slot *slot) { slot_printf(slot, "============== REGISTER DUMP ==============\n"); slot_printf(slot, "Sys addr: 0x%08x | Version: 0x%08x\n", RD4(slot, SDHCI_DMA_ADDRESS), RD2(slot, SDHCI_HOST_VERSION)); slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n", RD2(slot, SDHCI_BLOCK_SIZE), RD2(slot, SDHCI_BLOCK_COUNT)); slot_printf(slot, "Argument: 0x%08x | Trn mode: 0x%08x\n", RD4(slot, SDHCI_ARGUMENT), RD2(slot, SDHCI_TRANSFER_MODE)); slot_printf(slot, "Present: 0x%08x | Host ctl: 0x%08x\n", RD4(slot, SDHCI_PRESENT_STATE), RD1(slot, SDHCI_HOST_CONTROL)); slot_printf(slot, "Power: 0x%08x | Blk gap: 0x%08x\n", RD1(slot, SDHCI_POWER_CONTROL), RD1(slot, SDHCI_BLOCK_GAP_CONTROL)); slot_printf(slot, "Wake-up: 0x%08x | Clock: 0x%08x\n", RD1(slot, SDHCI_WAKE_UP_CONTROL), RD2(slot, SDHCI_CLOCK_CONTROL)); slot_printf(slot, "Timeout: 0x%08x | Int stat: 0x%08x\n", RD1(slot, SDHCI_TIMEOUT_CONTROL), RD4(slot, SDHCI_INT_STATUS)); slot_printf(slot, "Int enab: 0x%08x | Sig enab: 0x%08x\n", RD4(slot, SDHCI_INT_ENABLE), RD4(slot, SDHCI_SIGNAL_ENABLE)); slot_printf(slot, "AC12 err: 0x%08x | Slot int: 0x%08x\n", RD2(slot, SDHCI_ACMD12_ERR), RD2(slot, SDHCI_SLOT_INT_STATUS)); slot_printf(slot, "Caps: 0x%08x | Max curr: 0x%08x\n", RD4(slot, SDHCI_CAPABILITIES), RD4(slot, SDHCI_MAX_CURRENT)); slot_printf(slot, "===========================================\n"); }
static void ffec_miigasket_setup(struct ffec_softc *sc) { uint32_t ifmode; /* * We only need the gasket for MII and RMII connections on certain SoCs. */ switch (sc->fectype & FECTYPE_MASK) { case FECTYPE_IMX53: break; default: return; } switch (sc->phy_conn_type) { case PHY_CONN_MII: ifmode = 0; break; case PHY_CONN_RMII: ifmode = FEC_MIIGSK_CFGR_IF_MODE_RMII; break; default: return; } /* * Disable the gasket, configure for either MII or RMII, then enable. */ WR2(sc, FEC_MIIGSK_ENR, 0); while (RD2(sc, FEC_MIIGSK_ENR) & FEC_MIIGSK_ENR_READY) continue; WR2(sc, FEC_MIIGSK_CFGR, ifmode); WR2(sc, FEC_MIIGSK_ENR, FEC_MIIGSK_ENR_EN); while (!(RD2(sc, FEC_MIIGSK_ENR) & FEC_MIIGSK_ENR_READY)) continue; }
void ConeSplitMerge<Item>::split_merge(std::vector<ProtoJet<Item> >& jcv, float shared_ET_fraction, float pT_min_leading_protojet, float pT_min_second_protojet, int MergeMax, float pT_min_noMergeMax) { while(!_members.empty()) { /* { std::cout << std::endl; std::cout << " --------------- list of protojets ------------------ " <<std::endl; for ( PJMMAP::iterator it = _members.begin(); it != _members.end(); ++it) { std::cout << " pT y phi " << (*it).pT() << " " << (*it).y() << " " << (*it).phi() << " " << (*it).info().seedET() << " " << (*it).info().nbMerge() << " " << (*it).info().nbSplit() << std::endl; } std::cout << " ----------------------------------------------------- " <<std::endl; } */ // select highest Et jet typename PJMMAP::iterator itmax= _members.begin(); ProtoJet<Item> imax((*itmax).first); const std::list<const Item*>& ilist(imax.LItems()); _members.erase(itmax); // does jet share items? bool share= false; float shared_ET = 0.; typename PJMMAP::iterator jtmax; typename PJMMAP::iterator jt; for(jt = _members.begin(); jt != _members.end(); ++jt) { const std::list<const Item*>& jlist((*jt).first.LItems()); typename std::list<const Item*>::const_iterator tk; int count; for(tk = ilist.begin(), count = 0; tk != ilist.end(); ++tk, ++count) { typename std::list<const Item*>::const_iterator where= find(jlist.begin(),jlist.end(),*tk); if(where != jlist.end()) { share= true; shared_ET += (*tk)->pT(); } } if(share) { jtmax = jt; break; } } if(!share) { // add jet to the final jet list jcv.push_back(imax); //std::cout << " final jet " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; } else { // find highest Et neighbor ProtoJet<Item> jmax((*jtmax).first); // drop neighbor _members.erase(jtmax); //std::cout << " split or merge ? " << imax.pT() << " " << shared_ET << " " << jmax.pT() << " " << s << " " << (jmax.pT())*s << std::endl; // merge if( shared_ET > (jmax.pT())*shared_ET_fraction && (imax.pT() > pT_min_leading_protojet || jmax.pT() > pT_min_second_protojet) && (imax.info().nbMerge() < MergeMax || imax.pT() > pT_min_noMergeMax)) { // add neighbor's items to imax const std::list<const Item*>& jlist(jmax.LItems()); typename std::list<const Item*>::const_iterator tk; typename std::list<const Item*>::const_iterator iend= ilist.end(); bool same = true; // is jmax just the same as imax ? for(tk = jlist.begin(); tk != jlist.end(); ++tk) { typename std::list<const Item*>::const_iterator where= find(ilist.begin(),iend,*tk); if(where == iend) { imax.addItem(*tk); same = false; } } if ( ! same ) { // recalculate //float old_pT = imax.pT(); imax.updateJet(); imax.merged(); //std::cout << " jet merge :: " << old_pT << " " << jmax.pT() << " " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; } } //split and assign removed shared cells from lowest pT protojet else if(shared_ET > (jmax.pT())*shared_ET_fraction) { // here we need to pull the lists, because there are items to remove std::list<const Item*> ilist(imax.LItems()); std::list<const Item*> jlist(jmax.LItems()); typename std::list<const Item*>::iterator tk; for(tk = jlist.begin(); tk != jlist.end(); ) { typename std::list<const Item*>::iterator where= find(ilist.begin(),ilist.end(),*tk); if(where != ilist.end()) { tk = jlist.erase(tk); } else ++tk; } jmax.erase(); for ( typename std::list<const Item*>::const_iterator it = jlist.begin(); it != jlist.end(); ++it) jmax.addItem(*it); // recalculated jet quantities jmax.updateJet(); jmax.splitted(); //std::cout << " jet split 1 :: " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl; _members.insert(std::make_pair(jmax,jmax.pT())); } // split and assign shared cells to nearest protojet else { // here we need to pull the lists, because there are items to remove std::list<const Item*> ilist(imax.LItems()); std::list<const Item*> jlist(jmax.LItems()); typename std::list<const Item*>::iterator tk; for(tk = jlist.begin(); tk != jlist.end(); ) { typename std::list<const Item*>::iterator where= find(ilist.begin(),ilist.end(),*tk); if(where != ilist.end()) { float yk = (*tk)->y(); float phik = (*tk)->phi(); float di= RD2(imax.y(),imax.phi(),yk,phik); float dj= RD2(jmax.y(),jmax.phi(),yk,phik); if(dj > di) { tk = jlist.erase(tk); //std::cout << " shared item " << (*tk)->pT() << " removed from neighbour jet " << std::endl; } else { ilist.erase(where); ++tk; //std::cout << " shared item " << (*tk)->pT() << " removed from leading jet " << std::endl; } } else ++tk; } // recalculate jets imax and jmax // first erase all items imax.erase(); // put items that are left for ( typename std::list<const Item*>::const_iterator it = ilist.begin(); it != ilist.end(); ++it) imax.addItem(*it); // recalculated jet quantities imax.updateJet(); imax.splitted(); //std::cout << " jet split 2 :: " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; // first erase all items jmax.erase(); // put items that are left for ( typename std::list<const Item*>::const_iterator it = jlist.begin(); it != jlist.end(); ++it) jmax.addItem(*it); // recalculated jet quantities jmax.updateJet(); jmax.splitted(); //std::cout << " jet split " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl; _members.insert(std::make_pair(jmax,jmax.pT())); } _members.insert(std::make_pair(imax,imax.pT())); } } // while }
bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod) { for(unsigned long off = 0; off < img.debug_line_length; ) { DWARF_LineNumberProgramHeader* hdr = (DWARF_LineNumberProgramHeader*) (img.debug_line + off); int length = hdr->unit_length; if(length < 0) break; length += sizeof(length); unsigned char* p = (unsigned char*) (hdr + 1); unsigned char* end = (unsigned char*) hdr + length; std::vector<unsigned int> opcode_lengths; opcode_lengths.resize(hdr->opcode_base); if (hdr->opcode_base > 0) { opcode_lengths[0] = 0; for(int o = 1; o < hdr->opcode_base && p < end; o++) opcode_lengths[o] = LEB128(p); } DWARF_LineState state; state.seg_offset = img.getImageBase() + img.getSection(img.codeSegment).VirtualAddress; // dirs while(p < end) { if(*p == 0) break; state.include_dirs.push_back((const char*) p); p += strlen((const char*) p) + 1; } p++; // files DWARF_FileName fname; while(p < end && *p) { fname.read(p); state.files.push_back(fname); } p++; state.init(hdr); while(p < end) { int opcode = *p++; if(opcode >= hdr->opcode_base) { // special opcode int adjusted_opcode = opcode - hdr->opcode_base; int operation_advance = adjusted_opcode / hdr->line_range; state.advance_addr(hdr, operation_advance); int line_advance = hdr->line_base + (adjusted_opcode % hdr->line_range); state.line += line_advance; state.addLineInfo(); state.basic_block = false; state.prologue_end = false; state.epilogue_end = false; state.discriminator = 0; } else { switch(opcode) { case 0: // extended { int exlength = LEB128(p); unsigned char* q = p + exlength; int excode = *p++; switch(excode) { case DW_LNE_end_sequence: if((char*)p - img.debug_line >= 0xe4e0) p = p; state.end_sequence = true; state.last_addr = state.address; state.addLineInfo(); if(!_flushDWARFLines(img, mod, state)) return false; state.init(hdr); break; case DW_LNE_set_address: if (!mod && state.section == -1) state.section = img.getRelocationInLineSegment((char*)p - img.debug_line); if(unsigned long adr = RD4(p)) state.address = adr; else if (!mod) state.address = adr; else state.address = state.last_addr; // strange adr 0 for templates? state.op_index = 0; break; case DW_LNE_define_file: fname.read(p); state.file_ptr = &fname; state.file = 0; break; case DW_LNE_set_discriminator: state.discriminator = LEB128(p); break; } p = q; break; } case DW_LNS_copy: state.addLineInfo(); state.basic_block = false; state.prologue_end = false; state.epilogue_end = false; state.discriminator = 0; break; case DW_LNS_advance_pc: state.advance_addr(hdr, LEB128(p)); break; case DW_LNS_advance_line: state.line += SLEB128(p); break; case DW_LNS_set_file: if(!_flushDWARFLines(img, mod, state)) return false; state.file = LEB128(p); break; case DW_LNS_set_column: state.column = LEB128(p); break; case DW_LNS_negate_stmt: state.is_stmt = !state.is_stmt; break; case DW_LNS_set_basic_block: state.basic_block = true; break; case DW_LNS_const_add_pc: state.advance_addr(hdr, (255 - hdr->opcode_base) / hdr->line_range); break; case DW_LNS_fixed_advance_pc: state.address += RD2(p); state.op_index = 0; break; case DW_LNS_set_prologue_end: state.prologue_end = true; break; case DW_LNS_set_epilogue_begin: state.epilogue_end = true; break; case DW_LNS_set_isa: state.isa = LEB128(p); break; default: // unknown standard opcode for(unsigned int arg = 0; arg < opcode_lengths[opcode]; arg++) LEB128(p); break; } } } if(!_flushDWARFLines(img, mod, state)) return false; off += length; } return true; }
Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, int at) { static Location invalid = { Location::Invalid }; if (attr.type == Const) return mkAbs(attr.cons); if (attr.type != ExprLoc && attr.type != Block) // same memory layout return invalid; byte* p = attr.expr.ptr; Location stack[256]; int stackDepth = 0; if (at == DW_AT_data_member_location) stack[stackDepth++] = Location { Location::Abs, 0, 0 }; for (;;) { if (p >= attr.expr.ptr + attr.expr.len) break; int op = *p++; if (op == 0) break; switch (op) { case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: stack[stackDepth++] = mkInReg(op - DW_OP_reg0); break; case DW_OP_regx: stack[stackDepth++] = mkInReg(LEB128(p)); break; case DW_OP_const1u: stack[stackDepth++] = mkAbs(*p); break; case DW_OP_const2u: stack[stackDepth++] = mkAbs(RD2(p)); break; case DW_OP_const4u: stack[stackDepth++] = mkAbs(RD4(p)); break; case DW_OP_const1s: stack[stackDepth++] = mkAbs((char)*p); break; case DW_OP_const2s: stack[stackDepth++] = mkAbs((short)RD2(p)); break; case DW_OP_const4s: stack[stackDepth++] = mkAbs((int)RD4(p)); break; case DW_OP_constu: stack[stackDepth++] = mkAbs(LEB128(p)); break; case DW_OP_consts: stack[stackDepth++] = mkAbs(SLEB128(p)); break; case DW_OP_plus_uconst: if (stack[stackDepth - 1].is_inreg()) return invalid; stack[stackDepth - 1].off += LEB128(p); break; case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: stack[stackDepth++] = mkAbs(op - DW_OP_lit0); break; case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: stack[stackDepth++] = mkRegRel(op - DW_OP_breg0, SLEB128(p)); break; case DW_OP_bregx: { unsigned reg = LEB128(p); stack[stackDepth++] = mkRegRel(reg, SLEB128(p)); } break; case DW_OP_abs: case DW_OP_neg: case DW_OP_not: { Location& op1 = stack[stackDepth - 1]; if (!op1.is_abs()) return invalid; switch (op) { case DW_OP_abs: op1 = mkAbs(abs(op1.off)); break; case DW_OP_neg: op1 = mkAbs(-op1.off); break; case DW_OP_not: op1 = mkAbs(~op1.off); break; } } break; case DW_OP_plus: // op2 + op1 { Location& op1 = stack[stackDepth - 1]; Location& op2 = stack[stackDepth - 2]; // Can add only two offsets or a regrel and an offset. if (op2.is_regrel() && op1.is_abs()) op2 = mkRegRel(op2.reg, op2.off + op1.off); else if (op2.is_abs() && op1.is_regrel()) op2 = mkRegRel(op1.reg, op2.off + op1.off); else if (op2.is_abs() && op1.is_abs()) op2 = mkAbs(op2.off + op1.off); else return invalid; --stackDepth; } break; case DW_OP_minus: // op2 - op1 { Location& op1 = stack[stackDepth - 1]; Location& op2 = stack[stackDepth - 2]; if (op2.is_regrel() && op1.is_regrel() && op2.reg == op1.reg) op2 = mkAbs(0); // X - X == 0 else if (op2.is_regrel() && op1.is_abs()) op2 = mkRegRel(op2.reg, op2.off - op1.off); else if (op2.is_abs() && op1.is_abs()) op2 = mkAbs(op2.off - op1.off); else return invalid; --stackDepth; } break; case DW_OP_mul: { Location& op1 = stack[stackDepth - 1]; Location& op2 = stack[stackDepth - 2]; if ((op1.is_abs() && op1.off == 0) || (op2.is_abs() && op2.off == 0)) op2 = mkAbs(0); // X * 0 == 0 else if (op1.is_abs() && op2.is_abs()) op2 = mkAbs(op1.off * op2.off); else return invalid; --stackDepth; } break; case DW_OP_and: { Location& op1 = stack[stackDepth - 1]; Location& op2 = stack[stackDepth - 2]; if ((op1.is_abs() && op1.off == 0) || (op2.is_abs() && op2.off == 0)) op2 = mkAbs(0); // X & 0 == 0 else if (op1.is_abs() && op2.is_abs()) op2 = mkAbs(op1.off & op2.off); else return invalid; --stackDepth; } break; case DW_OP_div: case DW_OP_mod: case DW_OP_shl: case DW_OP_shr: case DW_OP_shra: case DW_OP_or: case DW_OP_xor: case DW_OP_eq: case DW_OP_ge: case DW_OP_gt: case DW_OP_le: case DW_OP_lt: case DW_OP_ne: { Location& op1 = stack[stackDepth - 1]; Location& op2 = stack[stackDepth - 2]; if (!op1.is_abs() || !op2.is_abs()) // can't combine unless both are constants return invalid; switch (op) { case DW_OP_div: op2.off = op2.off / op1.off; break; case DW_OP_mod: op2.off = op2.off % op1.off; break; case DW_OP_shl: op2.off = op2.off << op1.off; break; case DW_OP_shr: op2.off = op2.off >> op1.off; break; case DW_OP_shra: op2.off = op2.off >> op1.off; break; case DW_OP_or: op2.off = op2.off | op1.off; break; case DW_OP_xor: op2.off = op2.off ^ op1.off; break; case DW_OP_eq: op2.off = op2.off == op1.off; break; case DW_OP_ge: op2.off = op2.off >= op1.off; break; case DW_OP_gt: op2.off = op2.off > op1.off; break; case DW_OP_le: op2.off = op2.off <= op1.off; break; case DW_OP_lt: op2.off = op2.off < op1.off; break; case DW_OP_ne: op2.off = op2.off != op1.off; break; } --stackDepth; } break; case DW_OP_fbreg: { if (!frameBase) return invalid; Location loc; if (frameBase->is_inreg()) // ok in frame base specification, per DWARF4 spec #3.3.5 loc = mkRegRel(frameBase->reg, SLEB128(p)); else if (frameBase->is_regrel()) loc = mkRegRel(frameBase->reg, frameBase->off + SLEB128(p)); else return invalid; stack[stackDepth++] = loc; } break; case DW_OP_dup: stack[stackDepth] = stack[stackDepth - 1]; stackDepth++; break; case DW_OP_drop: stackDepth--; break; case DW_OP_over: stack[stackDepth] = stack[stackDepth - 2]; stackDepth++; break; case DW_OP_pick: stack[stackDepth++] = stack[*p]; break; case DW_OP_swap: { Location tmp = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = tmp; } break; case DW_OP_rot: { Location tmp = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = stack[stackDepth - 3]; stack[stackDepth - 3] = tmp; } break; case DW_OP_addr: stack[stackDepth++] = mkAbs(RD4(p)); // TODO: 64-bit break; case DW_OP_skip: { unsigned off = RD2(p); p = p + off; } break; case DW_OP_bra: { Location& op1 = stack[stackDepth - 1]; if (!op1.is_abs()) return invalid; if (op1.off != 0) { unsigned off = RD2(p); p = p + off; } --stackDepth; } break; case DW_OP_nop: break; case DW_OP_call_frame_cfa: // assume ebp+8/rbp+16 stack[stackDepth++] = Location{ Location::RegRel, DW_REG_CFA, 0 }; break; case DW_OP_deref: case DW_OP_deref_size: case DW_OP_push_object_address: case DW_OP_call2: case DW_OP_call4: case DW_OP_form_tls_address: case DW_OP_call_ref: case DW_OP_bit_piece: case DW_OP_implicit_value: case DW_OP_stack_value: default: return invalid; } } assert(stackDepth > 0); return stack[0]; }
bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) { id.clear(); if (hasChild) ++level; for (;;) { if (level == -1) return false; // we were already at the end of the subtree if (ptr >= ((byte*)cu + sizeof(cu->unit_length) + cu->unit_length)) return false; // root of the tree does not have a null terminator, but we know the length id.entryPtr = ptr; id.entryOff = ptr - (byte*)cu; id.code = LEB128(ptr); if (id.code == 0) { --level; // pop up one level if (stopAtNull) { hasChild = false; return false; } continue; // read the next DIE } break; } byte* abbrev = getDWARFAbbrev(cu->debug_abbrev_offset, id.code); assert(abbrev); if (!abbrev) return false; id.abbrev = abbrev; id.tag = LEB128(abbrev); id.hasChild = *abbrev++; int attr, form; for (;;) { attr = LEB128(abbrev); form = LEB128(abbrev); if (attr == 0 && form == 0) break; while (form == DW_FORM_indirect) form = LEB128(ptr); DWARF_Attribute a; switch (form) { case DW_FORM_addr: a.type = Addr; a.addr = (unsigned long)RDsize(ptr, cu->address_size); break; case DW_FORM_block: a.type = Block; a.block.len = LEB128(ptr); a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_block1: a.type = Block; a.block.len = *ptr++; a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_block2: a.type = Block; a.block.len = RD2(ptr); a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_block4: a.type = Block; a.block.len = RD4(ptr); a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_data1: a.type = Const; a.cons = *ptr++; break; case DW_FORM_data2: a.type = Const; a.cons = RD2(ptr); break; case DW_FORM_data4: a.type = Const; a.cons = RD4(ptr); break; case DW_FORM_data8: a.type = Const; a.cons = RD8(ptr); break; case DW_FORM_sdata: a.type = Const; a.cons = SLEB128(ptr); break; case DW_FORM_udata: a.type = Const; a.cons = LEB128(ptr); break; case DW_FORM_string: a.type = String; a.string = (const char*)ptr; ptr += strlen(a.string) + 1; break; case DW_FORM_strp: a.type = String; a.string = (const char*)(img->debug_str + RDsize(ptr, cu->isDWARF64() ? 8 : 4)); break; case DW_FORM_flag: a.type = Flag; a.flag = (*ptr++ != 0); break; case DW_FORM_flag_present: a.type = Flag; a.flag = true; break; case DW_FORM_ref1: a.type = Ref; a.ref = (byte*)cu + *ptr++; break; case DW_FORM_ref2: a.type = Ref; a.ref = (byte*)cu + RD2(ptr); break; case DW_FORM_ref4: a.type = Ref; a.ref = (byte*)cu + RD4(ptr); break; case DW_FORM_ref8: a.type = Ref; a.ref = (byte*)cu + RD8(ptr); break; case DW_FORM_ref_udata: a.type = Ref; a.ref = (byte*)cu + LEB128(ptr); break; case DW_FORM_ref_addr: a.type = Ref; a.ref = (byte*)img->debug_info + (cu->isDWARF64() ? RD8(ptr) : RD4(ptr)); break; case DW_FORM_ref_sig8: a.type = Invalid; ptr += 8; break; case DW_FORM_exprloc: a.type = ExprLoc; a.expr.len = LEB128(ptr); a.expr.ptr = ptr; ptr += a.expr.len; break; case DW_FORM_sec_offset: a.type = SecOffset; a.sec_offset = cu->isDWARF64() ? RD8(ptr) : RD4(ptr); break; case DW_FORM_indirect: default: assert(false && "Unsupported DWARF attribute form"); return false; } switch (attr) { case DW_AT_byte_size: assert(a.type == Const || a.type == Ref || a.type == ExprLoc); if (a.type == Const) // TODO: other types not supported yet id.byte_size = a.cons; break; case DW_AT_sibling: assert(a.type == Ref); id.sibling = a.ref; break; case DW_AT_encoding: assert(a.type == Const); id.encoding = a.cons; break; case DW_AT_name: assert(a.type == String); id.name = a.string; break; case DW_AT_MIPS_linkage_name: assert(a.type == String); id.linkage_name = a.string; break; case DW_AT_comp_dir: assert(a.type == String); id.dir = a.string; break; case DW_AT_low_pc: assert(a.type == Addr); id.pclo = a.addr; break; case DW_AT_high_pc: if (a.type == Addr) id.pchi = a.addr; else if (a.type == Const) id.pchi = id.pclo + a.cons; else assert(false); break; case DW_AT_ranges: if (a.type == SecOffset) id.ranges = a.sec_offset; else if (a.type == Const) id.ranges = a.cons; else assert(false); break; case DW_AT_type: assert(a.type == Ref); id.type = a.ref; break; case DW_AT_inline: assert(a.type == Const); id.inlined = a.cons; break; case DW_AT_external: assert(a.type == Flag); id.external = a.flag; break; case DW_AT_upper_bound: assert(a.type == Const || a.type == Ref || a.type == ExprLoc); if (a.type == Const) // TODO: other types not supported yet id.upper_bound = a.cons; break; case DW_AT_lower_bound: assert(a.type == Const || a.type == Ref || a.type == ExprLoc); if (a.type == Const) // TODO: other types not supported yet id.lower_bound = a.cons; break; case DW_AT_containing_type: assert(a.type == Ref); id.containing_type = a.ref; break; case DW_AT_specification: assert(a.type == Ref); id.specification = a.ref; break; case DW_AT_data_member_location: id.member_location = a; break; case DW_AT_location: id.location = a; break; case DW_AT_frame_base: id.frame_base = a; break; } } hasChild = id.hasChild != 0; sibling = id.sibling; return true; }