LCOV - code coverage report
Current view: top level - atrace/utrace/stacktrace/stacktrace_dumper - scd_frames.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 18.4 % 87 16
Test Date: 2026-07-28 10:53:44 Functions: 40.0 % 5 2

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "scd_frames.h"
      12              : #include "scd_regs.h"
      13              : #include "scd_maps.h"
      14              : #include "scd_log.h"
      15              : #include "scd_dl.h"
      16              : #include "scd_frame.h"
      17              : 
      18              : #define SCD_MAX_STACK_LAYER         32U
      19              : 
      20            0 : STATIC TraStatus ScdFramesFpStep(ScdFrame *frame, ScdRegs *regs)
      21              : {
      22            0 :     uintptr_t fp = frame->fp;
      23            0 :     SCD_CHK_EXPR_ACTION(fp == 0, return TRACE_FAILURE, "invalid fp 0, frame pointer is not supported");
      24            0 :     uintptr_t lr = fp + 8U;  // LR_OFFSET
      25              :     uintptr_t nextPc;
      26              :     /* ScdMemoryRead(NULL, ...) uses global handler (ScdMemoryRemoteRead via ptrace).
      27              :      * Safe here: this function is only called from dumper subprocess context
      28              :      * (ScdProcessDump -> ScdFramesLoad), where ptrace is available. */
      29            0 :     size_t size = ScdMemoryRead(NULL, lr, &nextPc, sizeof(uintptr_t));
      30            0 :     SCD_CHK_EXPR_ACTION(size == 0, return TRACE_FAILURE, "scd read memory from 0x%llx, failed ", lr);
      31            0 :     ScdRegsSetPc(regs, nextPc);
      32            0 :     SCD_DLOG_INF("update pc to 0x%llx get from 0x%llx",nextPc, lr);
      33              : 
      34              :     uintptr_t nextFp;
      35            0 :     size = ScdMemoryRead(NULL, fp, &nextFp, sizeof(uintptr_t));
      36            0 :     SCD_CHK_EXPR_ACTION(size == 0, return TRACE_FAILURE, "scd read memory from 0x%llx, failed ", fp);
      37            0 :     ScdRegsSetFp(regs, nextFp);
      38            0 :     SCD_DLOG_INF("update fp to 0x%llx get from 0x%llx", nextFp, fp);
      39            0 :     return TRACE_SUCCESS;
      40              : }
      41              : 
      42            0 : STATIC ScdFrame *ScdFramesCreateFrame(ScdFrames *frames, uintptr_t pc, uintptr_t sp, uintptr_t fp)
      43              : {
      44            0 :     ScdMap *map = ScdMapsGetMapByPc(frames->maps, pc);
      45            0 :     if (map == NULL) {
      46            0 :         SCD_DLOG_ERR("can not find map, pc = %p, sp = %p.", pc, sp);
      47            0 :         return NULL;
      48              :     }
      49            0 :     SCD_DLOG_INF("find pc 0x%llx in map %s",pc, map->name);
      50              : 
      51            0 :     TraStatus ret = ScdDlLoad(&map->dl, frames->pid, map->name);
      52            0 :     if (ret != TRACE_SUCCESS) {
      53            0 :         SCD_DLOG_ERR("load map(%s) failed, pc = %p, sp = %p.", map->name, pc, sp);
      54            0 :         return NULL;
      55              :     }
      56            0 :     uintptr_t relPc = ScdMapGetRelPc(map, pc);
      57            0 :     ScdFrame *frame = ScdFrameCreate(map, pc, sp, fp);
      58            0 :     if (frame == NULL) {
      59            0 :         SCD_DLOG_ERR("create frame failed, map = %s, pc = %p, sp = %p.", map->name, pc, sp);
      60            0 :         return NULL;
      61              :     }
      62            0 :     frame->base = ScdMapGetBase(map);
      63            0 :     frame->num = frames->framesNum;
      64            0 :     frame->tid = frames->tid;
      65            0 :     frame->relPc = relPc;
      66              : 
      67            0 :     if (AdiagListInsert(&frames->frameList, frame) != ADIAG_SUCCESS) {
      68            0 :         SCD_DLOG_ERR("insert frame to list failed, map = %s, pc = %p, sp = %p.", map->name, pc, sp);
      69            0 :         ScdFrameDestroy(&frame);
      70            0 :         return NULL;
      71              :     }
      72            0 :     frames->framesNum++;
      73            0 :     ScdElfGetFunctionInfo(&map->dl.elf, relPc, frame->funcName, SCD_FUNC_NAME_LENGTH, &frame->funcOffset);
      74              : 
      75            0 :     SCD_DLOG_DBG("map info: name = %s, start = 0x%lx, end = 0x%lx, memory data = 0x%lx, loadBias = 0x%lx.",
      76              :         map->name, map->start, map->end, map->dl.elf.memory->data, map->dl.elf.loadBias);
      77            0 :     SCD_DLOG_DBG("create thread(%d) frame[%u] successfully,"
      78              :                  " pc = %p, relPc = %p, base = %p, sp = %p, fp = %p, function(%s: %d).",
      79              :                  frames->tid, frame->num, frame->pc, frame->relPc, frame->base, frame->sp, frame->fp,
      80              :                  strlen(frame->funcName) != 0 ? frame->funcName : "unknown", frame->funcOffset);
      81            0 :     return frame;
      82              : }
      83              : 
      84            0 : TraStatus ScdFramesLoad(ScdFrames *frames, ScdMaps *maps, ScdRegs *regs)
      85              : {
      86            0 :     SCD_CHK_PTR_ACTION(frames, return TRACE_FAILURE);
      87            0 :     SCD_CHK_PTR_ACTION(maps, return TRACE_FAILURE);
      88            0 :     SCD_CHK_PTR_ACTION(regs, return TRACE_FAILURE);
      89            0 :     frames->regs = regs;
      90            0 :     frames->maps = maps;
      91            0 :     ScdRegs frameRegs = *(frames->regs);
      92            0 :     while (frames->framesNum < SCD_MAX_STACK_LAYER) {
      93            0 :         uintptr_t framePc = ScdRegsGetPc(&frameRegs);
      94            0 :         uintptr_t frameSp = ScdRegsGetSp(&frameRegs);
      95            0 :         uintptr_t frameFp = ScdRegsGetFp(&frameRegs);
      96              : 
      97              :         // 1. create new frame
      98            0 :         ScdFrame *frame = ScdFramesCreateFrame(frames, framePc, frameSp, frameFp);
      99            0 :         if (frame == NULL) {
     100            0 :             SCD_DLOG_ERR("create frame failed.");
     101            0 :             return TRACE_FAILURE;
     102              :         }
     103              : 
     104              :         // 2. do step, get next frame regs
     105            0 :         TraStatus ret = ScdElfStep(&frame->map->dl.elf, frame->relPc, &frameRegs, frames->framesNum == 1);
     106            0 :         if (ret != TRACE_SUCCESS) {
     107            0 :             SCD_DLOG_WAR("get from regs, pc = 0x%lx, sp = 0x%lx, fp = 0x%lx.", framePc, frameSp, frameFp);
     108            0 :             SCD_DLOG_WAR("can not step by elf, pid = %d, tid = %d, num = %u, pc = 0x%lx, sp = 0x%lx, fp = 0x%lx.",
     109              :                 frames->maps->pid, frame->tid, frames->framesNum, frame->pc, frame->sp, frame->fp);
     110            0 :             ret = ScdFramesFpStep(frame, &frameRegs);
     111            0 :             if (ret != TRACE_SUCCESS) {
     112            0 :                 SCD_DLOG_ERR("step by fp failed, pid = %d, tid = %d, num = %u, pc = 0x%lx, sp = 0x%lx, fp = 0x%lx.",
     113              :                     frames->maps->pid, frame->tid, frames->framesNum, frame->pc, frame->sp, frame->fp);
     114            0 :                 return TRACE_FAILURE;
     115              :             }
     116              :         }
     117            0 :         if (ScdRegsGetPc(&frameRegs) == 0) {
     118            0 :             break;
     119              :         }
     120              :         // 3. if the pc and sp didn't change, stop.
     121            0 :         if ((framePc == ScdRegsGetPc(&frameRegs)) && (frameSp == ScdRegsGetSp(&frameRegs))) {
     122            0 :             break;
     123              :         }
     124              :     }
     125            0 :     return TRACE_SUCCESS;
     126              : }
     127              : 
     128           15 : TraStatus ScdFramesInit(ScdFrames *frames, int32_t pid, int32_t tid)
     129              : {
     130           15 :     SCD_CHK_PTR_ACTION(frames, return TRACE_FAILURE);
     131           15 :     frames->pid = pid;
     132           15 :     frames->tid = tid;
     133           15 :     frames->regs = NULL;
     134           15 :     frames->maps = NULL;
     135           15 :     frames->framesNum = 0;
     136           15 :     AdiagStatus adiagRet = AdiagListInit(&frames->frameList);
     137           15 :     if (adiagRet != ADIAG_SUCCESS) {
     138            0 :         SCD_DLOG_ERR("frame list of frames init failed, pid = %d, tid = %d.", pid, tid);
     139            0 :         return TRACE_FAILURE;
     140              :     }
     141           15 :     return TRACE_SUCCESS;
     142              : }
     143              : 
     144           15 : void ScdFramesUninit(ScdFrames *frames)
     145              : {
     146           15 :     SCD_CHK_PTR_ACTION(frames, return);
     147           15 :     ScdFrame *node = (ScdFrame *)AdiagListTakeOut(&frames->frameList);
     148           30 :     while (node != NULL) {
     149           15 :         ScdFrameDestroy(&node);
     150           15 :         node = (ScdFrame *)AdiagListTakeOut(&frames->frameList);
     151              :     }
     152              : }
        

Generated by: LCOV version 2.0-1