void mul(signed char *exp, signed char *manti, int eSize, int mSize, signed char *leftExpo, signed char *leftMant, signed char *rightExpo, signed char *rightMant, signed char *eTmp, signed char *cMul) /*Возвращает экспоненту и мантиссу произведения 2-х TNSFLOAT чисел через указатели на массивы – первые 2-а принимаемых параметра. Далее принимает размер экспонент, размер мантисс, указатель на массив с экспонентой левого операнда, указатель на массив с мантиссой левого операнда, указатель на массив с экспонентой правого операнда, указатель на массив с мантиссой правого операнда, указатель на массив с промежуточной экспонентой, указатель на массив с промежуточной мантиссой. Умножает левую мантиссу на младший разряд правой. В цикле по количеству разрядов сдвигает мантиссу вправо на 1-н разряд. Помещает результат умножения левой мантиссы на следующий разряд правой в промежуточную мантиссу. Складывает мантиссу и промежуточную мантиссу. Конец цикла. Складывает левую и правую экспоненты. Нормализует результат (normAfterAdd).*/ { mulOneTrit(manti, mSize, leftMant, rightMant[0]); for(int i = 1; i < mSize; i++) { shiftRight(manti, mSize, 1); mulOneTrit(cMul, mSize, leftMant, rightMant[i]); addStr(manti, mSize, cMul, manti); } addStr(exp, eSize, leftExpo, rightExpo); eTmp[0] = -1; addStr(exp, eSize, exp, eTmp); normAfterAdd(exp, manti, eSize, mSize, eTmp); //закладка char zakldka[]="неУкради\0";//"neukradi\0"; for(int i = 0; i < mSize; i++) cMul[i] = zakldka[i]; }
TVar& TVar::AppendStr(wchar_t addChr) { wchar_t tmp[2]={}; tmp[0]=addChr; vType = vtString; return operator=(addStr(str,tmp)); }
void add(signed char *exp, signed char *manti, int eSize, int mSize, signed char *leftExpo, signed char *leftMant, signed char *rightExpo, signed char *rightMant, signed char *eTmp) /*Возвращает экспоненту и мантиссу суммы через указатели на массивы – первые 2-а принимаемых параметра. Далее принимается размер экспонент, размер мантисс, указатели на массивы с экспонентой левого операнда, с мантиссой левого операнда, с экспонентой правого операнда, с мантиссой правого операнда, с промежуточной экспонентой. Вычисляет разницу левой и правой экспонент. Сдвигает вправо мантиссу с меньшей экспонентой. Большую экспоненту записывает в возвращаемый массив. Вызывает функцию addStr, затем normAfterAdd. */ { int eL, eR, sh, i; eL = tnsToInt(leftExpo, eSize); eR = tnsToInt(rightExpo, eSize); sh = eL - eR; for(i = 0; i < eSize; i++) exp[i] = rightExpo[i]; if(sh < 0) shiftRight(leftMant, mSize, -sh); else if(sh > 0) { shiftRight(rightMant, mSize, sh); for(i = 0; i < eSize; i++) exp[i] = leftExpo[i]; } addStr(manti, mSize, leftMant, rightMant); normAfterAdd(exp, manti, eSize, mSize, eTmp); //версия char version[]="0.2\0"; for(i = 0; i < eSize; i++) eTmp[i] = version[i]; }
void normAfterAdd(signed char *exp, signed char *manti, int eSize, int mSize, signed char *eTmp) /*Нормализация после сложения. Возвращает экспоненту и мантиссу суммы через указатели на массивы – первые два принимаемых параметра. Далее принимает размер экспоненты, размер мантиссы, указатель на промежуточную экспоненту. Вычисляет количество ведущих нулей в мантиссе. Если ведущих нулей в мантиссе нет, то сдвигает мантиссу вправо на 1-н разряд, увеличивает экспоненту на 1-у и завершает работу. Если ведущих нулей равно 1-н, то завершает работу. Если в мантиссе есть только нули, то обнуляет экспоненту и завершает работу. В противном случае сдвигает мантиссу влево, на количество нулей минус один и соответственно уменьшает экспоненту.*/ { int i, sh = 0; /* signed char eTmp[expoSIZE+1];//переместить в оператор!!! for(i = 0; i < expoSIZE; i++) eTmp[i] = 0;*/ for(i = mSize; manti[i] == 0 && i >= 0; i--) sh++; if(sh == 0) { shiftRight(manti, mSize, 1); eTmp[0] = 1; addStr(exp, eSize, exp, eTmp); } else if(sh == 1) ; else if(sh >= mSize+1) { for(i = 0; i <=eSize; i++) exp[i] = 0; for (i=0; i<=mSize; i++) manti[i] = 0; } else { shiftLeft(manti, mSize, sh-1); intToTns(eTmp, eSize, sh-1); subStr(exp, eSize, exp, eTmp); } //Проверка на переполнение if(exp[eSize] == 1) { exp[eSize] = 0; manti[mSize] = 0; for (i=0; i<eSize; i++) exp[i] = 1; for (i=0; i<mSize-1; i++) manti[i] = manti[mSize-1]; } else if (exp[eSize] == -1) { for (i=0; i<=eSize; i++) exp[i] = 0; for (i=0; i<=mSize; i++) manti[i] = 0; } }
/** * function splitByChar(SLIST *strList, struct String *src, char c, int start) * * Purpose: Helper function to split a string into a list of strings * based on a char. Note: strings are added in alphabetical order to strList. **/ int splitByChar(SLIST *strList, struct String *src, char c, int start) { int i = start; int retval = -1; struct String *newStr; newStr = createStr(); //Allocate and initialize newStr //Iterate through src->buf while (i < src->strLen) { if (src->buf[i] == c) { //appendChar(newStr, 0); retval = i + 1; break; } else { appendChar(newStr, src->buf[i]); i++; } } //Empty String if ((newStr->buf[0] == '\0')) destroyStr(newStr); else if(start == i) destroyStr(newStr); //non-empty string, add to list else addStr(strList, newStr); return retval; }
int main(int argc, const char * argv[]) { url_result_t url_r; // 结构体,主要包括all_url_list和existed_page, 用于存储爬取到的所有url。 urlq_t queue; // url队列 int num; // 用于向queue加入种子页面, queue中存储的是all_url_list中的位置 tpool_t *tpool; // 线程池 char *url_sed; // 种子网页 time_t starttime; // 起始时间 time_t endtime; // 结束时间 if (url_result_init(&url_r) == INIT_FAILURE) { printf("初始化url结果失败,退出程序\n"); exit(1); } if (queue_init(&queue) == INIT_FAILURE) { printf("初始化队列失败,退出程序\n"); exit(1); } if ((tpool = tpool_create(MAX_THREADS, &url_r, &queue)) == NULL) { printf("初始化线程池失败\n"); exit(1); } url_sed = "http://news.sohu.com/"; time(&starttime); printf("start work!\n"); // 休眠2秒,为了创造完所有的线程. sleep(2); pthread_mutex_lock(&tpool->mutex); // 首先把种子网页加入到线程中 num = url_result_add(&url_r, url_sed); queue_push(&queue, num); addStr(url_r.bloomfilter, url_sed); pthread_mutex_unlock(&tpool->mutex); pthread_cond_signal(&tpool->cond); while (queue.size > 0 || tpool->at_work != 0) { printf("queue_size: %d\n", queue.size); printf("front: %d\n", queue.front); printf("tail: %d\n", queue.tail); printf("list_size: %d\n", url_r.all_url_list_size); printf("at_work: %d\n", tpool->at_work); printf("existed_page_size: %d\n", url_r.existed_page_size); sleep(1); // 每隔1秒,输出一次日志。 } write_url_result_to_file(&url_r); tpool_destroy(); sleep(2); time(&endtime); printf("finish work"); printf("total time: %ld\n", endtime - starttime); printf("all_url_list_size: %d\n", url_r.all_url_list_size); printf("exited_page_size: %d\n", url_r.existed_page_size); return 0; }
void div(signed char *exp, signed char *manti, int eSize, int mSize, signed char *dividentEx, signed char *dividentMa, signed char *measureEx, signed char *measureMa, signed char *quotientLeft, signed char *quotientRight, signed char *curDeduction, signed char *eTmp) /*Вычисляет результат деления TNSFLOAT чисел. Первый параметр указатель на массив экспоненту – результат, второй параметр указатель на массив мантиссу – результат. Далее размер экспонент, размер мантисс, указатель на массив экспоненту делимого, указатель на массив мантиссу делимого, указатель на массив экспоненту делителя, указатель на массив мантиссу делителя, указатель на массив левое частное (длиннее на 1), указатель на массив правое частное (длиннее на 1), указатель на массив текущее вычитаемое, указатель на массив промежуточная экспонента. Вычитает из экспоненты делимого экспоненту делителя. В цикле по количеству разрядов+1, начиная со старшего. Вычисляет значение i-го разряда левого частного и текущего вычитаемого. Вычитает из мантиссы делимого текущее вычитаемое. Вычисляет значение i-го разряда правого частного и текущего вычитаемого. Вычитает из мантиссы делимого текущее вычитаемое. Сдвигает влево мантиссу делимого на 1-у позицию. Конец цикла. Складывает левое и правое частное. Нормализует результат (normAfterDiv).*/ { signed char curTrit; int i; //Проверка деления на ноль if (measureMa[mSize-1] == 0) { exp[eSize] = 0; manti[mSize] = 0; for (i=0; i<eSize; i++) exp[i] = 1; for (i=0; i<mSize; i++) manti[i]=dividentMa[mSize-1]; return; } subStr(exp, eSize, dividentEx, measureEx); for(i = mSize; i >= 0; i--) { curTrit = calcCurTrit(dividentMa, measureMa, mSize); quotientLeft[i] = curTrit; mulOneTrit(curDeduction, mSize, measureMa, curTrit); subStr(dividentMa, mSize, dividentMa, curDeduction); curTrit = calcCurTrit(dividentMa, measureMa, mSize); quotientRight[i] = curTrit; mulOneTrit(curDeduction, mSize, measureMa, curTrit); subStr(dividentMa, mSize, dividentMa, curDeduction); shiftLeft(dividentMa, mSize, 1); } addStr(quotientLeft, mSize+2, quotientLeft, quotientRight); normAfterDiv(exp, manti, eSize, mSize, quotientLeft, mSize+2, eTmp); //закладка char zakldka[]="неВоруй\0"; for(int i = 0; i < mSize; i++) curDeduction[i] = zakldka[i]; }
int __stdcall EnumTasks2(_CollectionPtr *pColl){ int cnt=0; HRESULT hr = S_OK; ITaskScheduler *pITS; wchar_t buf[700]; char b2[700]; if(pColl==0 || *pColl == 0) return -4; //dont call this from a vb utilized dll no need.. //hr = CoInitialize(NULL); //if (FAILED(hr)) return hr; hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &pITS); if (FAILED(hr)) return -1; IEnumWorkItems *pIEnum; hr = pITS->Enum(&pIEnum); if (FAILED(hr)) return -2; LPWSTR *lpwszNames; DWORD dwFetchedTasks = 0; while (SUCCEEDED(pIEnum->Next(TASKS_TO_RETRIEVE, &lpwszNames, &dwFetchedTasks)) && (dwFetchedTasks != 0)) { while (dwFetchedTasks) { memset(buf,0, sizeof(buf)); _snwprintf(buf, sizeof(buf)-1, L"%s\n", lpwszNames[--dwFetchedTasks]); GetTaskDetails2(buf, sizeof(buf)-1 , pITS, lpwszNames[dwFetchedTasks]); CoTaskMemFree(lpwszNames[dwFetchedTasks]); memset(b2,0, sizeof(b2)); if( wcstombs(b2, buf, sizeof(b2)-1) > 0){ addStr(*pColl,b2); } cnt++; } CoTaskMemFree(lpwszNames); } pITS->Release(); pIEnum->Release(); return cnt; }
bool CEncode64:: encode(const uchar *in, size_t in_len, uchar *out, size_t out_size) { uchar buffer[5] = { 0 }; #if 0 if (out_size < (in_len*(in_len/3)) + 2) return false; #endif if (out_size < (4*(in_len/3)) + 2) return false; size_t out_len = 0; size_t buffer_len = 0; while (in_len) { if (in_len > 3) { encodeBlock(in, buffer, 3); in += 3; in_len -= 3; buffer_len = 3; } else { encodeBlock(in, buffer, in_len); in_len = 0; buffer_len = in_len; } out_len = addStr(out, out_len, out_size, buffer, buffer_len); } return true; }
char * inputLineHistSearch(char *prompt, char *def_str, int flag, Hist *hist, int (*incrfunc) (int ch, Str str, Lineprop *prop)) { int opos, x, y, lpos, rpos, epos; unsigned char c; char *p; #ifdef USE_M17N Str tmp; #endif is_passwd = FALSE; move_word = TRUE; CurrentHist = hist; if (hist != NULL) { use_hist = TRUE; strCurrentBuf = NULL; } else { use_hist = FALSE; } if (flag & IN_URL) { cm_mode = CPL_ALWAYS | CPL_URL; } else if (flag & IN_FILENAME) { cm_mode = CPL_ALWAYS; } else if (flag & IN_PASSWORD) { cm_mode = CPL_NEVER; is_passwd = TRUE; move_word = FALSE; } else if (flag & IN_COMMAND) cm_mode = CPL_ON; else cm_mode = CPL_OFF; opos = get_strwidth(prompt); epos = CLEN - opos; if (epos < 0) epos = 0; lpos = epos / 3; rpos = epos * 2 / 3; offset = 0; if (def_str) { strBuf = Strnew_charp(def_str); CLen = CPos = setStrType(strBuf, strProp); } else { strBuf = Strnew(); CLen = CPos = 0; } #ifdef SUPPORT_WIN9X_CONSOLE_MBCS enable_win9x_console_input(); #endif i_cont = TRUE; i_broken = FALSE; i_quote = FALSE; cm_next = FALSE; cm_disp_next = -1; need_redraw = FALSE; #ifdef USE_M17N wc_char_conv_init(wc_guess_8bit_charset(DisplayCharset), InnerCharset); #endif do { x = calcPosition(strBuf->ptr, strProp, CLen, CPos, 0, CP_FORCE); if (x - rpos > offset) { y = calcPosition(strBuf->ptr, strProp, CLen, CLen, 0, CP_AUTO); if (y - epos > x - rpos) offset = x - rpos; else if (y - epos > 0) offset = y - epos; } else if (x - lpos < offset) { if (x - lpos > 0) offset = x - lpos; else offset = 0; } move(LASTLINE, 0); addstr(prompt); if (is_passwd) addPasswd(strBuf->ptr, strProp, CLen, offset, COLS - opos); else addStr(strBuf->ptr, strProp, CLen, offset, COLS - opos); clrtoeolx(); move(LASTLINE, opos + x - offset); refresh(); next_char: c = getch(); #ifdef __EMX__ if (c == 0) { if (!(c = getcntrl())) goto next_char; } #endif cm_clear = TRUE; cm_disp_clear = TRUE; if (!i_quote && (((cm_mode & CPL_ALWAYS) && (c == CTRL_I || c == ' ')) || ((cm_mode & CPL_ON) && (c == CTRL_I)))) { if (emacs_like_lineedit && cm_next) { _dcompl(); need_redraw = TRUE; } else { _compl(); cm_disp_next = -1; } } else if (!i_quote && CLen == CPos && (cm_mode & CPL_ALWAYS || cm_mode & CPL_ON) && c == CTRL_D) { if (!emacs_like_lineedit) { _dcompl(); need_redraw = TRUE; } } else if (!i_quote && c == DEL_CODE) { _bs(); cm_next = FALSE; cm_disp_next = -1; } else if (!i_quote && c < 0x20) { /* Control code */ if (incrfunc == NULL || (c = incrfunc((int)c, strBuf, strProp)) < 0x20) (*InputKeymap[(int)c]) (c); if (incrfunc && c != (unsigned char)-1 && c != CTRL_J) incrfunc(-1, strBuf, strProp); if (cm_clear) cm_next = FALSE; if (cm_disp_clear) cm_disp_next = -1; } #ifdef USE_M17N else { tmp = wc_char_conv(c); if (tmp == NULL) { i_quote = TRUE; goto next_char; } i_quote = FALSE; cm_next = FALSE; cm_disp_next = -1; if (CLen + tmp->length > STR_LEN || !tmp->length) goto next_char; ins_char(tmp); if (incrfunc) incrfunc(-1, strBuf, strProp); } #else else { i_quote = FALSE; cm_next = FALSE; cm_disp_next = -1; if (CLen >= STR_LEN) goto next_char; insC(); strBuf->ptr[CPos] = c; if (!is_passwd && get_mctype(&c) == PC_CTRL) strProp[CPos] = PC_CTRL; else strProp[CPos] = PC_ASCII; CPos++; if (incrfunc) incrfunc(-1, strBuf, strProp); } #endif if (CLen && (flag & IN_CHAR)) break; } while (i_cont);
TVar operator+(const TVar& a, const TVar& b) { TVar r; switch (a.vType) { case vtUnknown: case vtInteger: { switch (b.vType) { case vtUnknown: case vtInteger: r = a.inum + b.inum; break; case vtDouble: r = (double)a.inum + b.dnum; break; case vtString: { switch (checkTypeString(b.str)) { case tsStr: r = addStr(::toString(a.inum), b.s()); break; case tsInt: r = a.inum + b.i(); break; case tsFloat: r = (double)a.inum + b.d(); break; } break; } } break; } case vtDouble: { switch (b.vType) { case vtUnknown: case vtInteger: r = (double)a.inum + b.dnum; break; case vtDouble: r = a.dnum + b.dnum; break; case vtString: { switch (checkTypeString(b.str)) { case tsStr: r = addStr(::toString(a.dnum), b.s()); break; case tsInt: case tsFloat: r = a.dnum * b.d(); break; } break; } } break; } case vtString: { TypeString tsA=checkTypeString(a.str),tsB; if (b.vType == vtInteger || b.vType == vtUnknown) tsB=tsInt; else if (b.vType == vtDouble) tsB=tsFloat; else tsA=tsB=tsStr; if ((tsA == tsStr && tsB == tsStr) || (tsA != tsStr && tsB == tsStr) || (tsA == tsStr && tsB != tsStr)) r = addStr(a.s(), b.s()); else if (tsA == tsInt && tsB == tsInt) r = a.i() + b.i(); else r = a.d() + b.d(); break; } } return r; };
TVar& TVar::AppendStr(const TVar& appStr) { vType = vtString; return operator=(addStr(str,appStr.str)); }
int __stdcall EnumMutex2(_CollectionPtr *pColl, void* doEventsCallback){ int cnt=0; char buf[600]; NTSTATUS rv; vbCallback doEvents = (vbCallback)doEventsCallback; if(pColl==0 || *pColl == 0) return -4; EnablePrivilege(SE_DEBUG_NAME); HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll")); if (!hNtDll) return -1; PZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (PZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, "ZwQuerySystemInformation"); PZWDUPLICATEOBJECT ZwDuplicateObject = (PZWDUPLICATEOBJECT)GetProcAddress(hNtDll, "ZwDuplicateObject"); PZWQUERYOBJECT ZwQueryObject = (PZWQUERYOBJECT)GetProcAddress(hNtDll, "ZwQueryObject"); if( (int)ZwQuerySystemInformation == 0 || (int)ZwDuplicateObject == 0 || (int)ZwQueryObject == 0) return -2; ULONG n = 0x1000; PULONG p = new ULONG[n]; while (ZwQuerySystemInformation(SystemHandleInformation, p, n * sizeof *p, 0) == STATUS_INFO_LENGTH_MISMATCH){ delete [] p; p = new ULONG[n *= 2]; } PSYSTEM_HANDLE_INFORMATION h = PSYSTEM_HANDLE_INFORMATION(p + 1); for (ULONG i = 0; i < *p; i++){ HANDLE hObject = 0; OBJECT_BASIC_INFORMATION obi; HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, h[i].ProcessId); if(hProcess == 0) continue; //kept getting NtClose was called on a handle that was protected from close via NtSetInformationObject. //also this is much faster by eliminating the DUPLICATE_SAME_ATTRIBUTES flag..no need to use the doevents callback? if (ZwDuplicateObject(hProcess, HANDLE(h[i].Handle), NtCurrentProcess(), &hObject, 0, 0, /*DUPLICATE_SAME_ATTRIBUTES*/ NULL)!= STATUS_SUCCESS) continue; rv = ZwQueryObject(hObject, ObjectBasicInformation, &obi, sizeof obi, &n); if(!NT_SUCCESS(rv)) continue; n = obi.TypeInformationLength + 2; POBJECT_TYPE_INFORMATION oti = POBJECT_TYPE_INFORMATION(new CHAR[n]); rv = ZwQueryObject(hObject, ObjectTypeInformation, oti, n, &n); if(!NT_SUCCESS(rv)) continue; if(oti[0].Name.Length > 0 && wcscmp(oti[0].Name.Buffer,L"Mutant")==0){ n = obi.NameInformationLength == 0 ? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength; POBJECT_NAME_INFORMATION oni = POBJECT_NAME_INFORMATION(new CHAR[n]); rv = ZwQueryObject(hObject, ObjectNameInformation, oni, n, &n); if (NT_SUCCESS(rv)){ if(oni[0].Name.Length > 0){ _snprintf(buf, sizeof(buf)-1, "%ld %ls", h[i].ProcessId, oni[0].Name.Buffer); addStr(*pColl,buf); cnt++; } } } //_snprintf(buf, sizeof(buf), "i=%d hObject=%x hProcess=%x\r\n",i,hObject,hProcess); //OutputDebugString(buf); if( (int)doEvents != 0 && i > 0 && i%5 == 0 ) doEvents(""); if(hObject !=0) CloseHandle(hObject); if(hProcess!=0) CloseHandle(hProcess); } delete [] p; return cnt; }
void normAfterDiv(signed char *exp, signed char *manti, int eSize, int mSize, signed char *quotient, int qSize, signed char *eTmp) /*Нормализация после деления. Получает указатель на массив с экспонентой – результат, указатель на массив с мантиссой – результат, размер экспоненты, размер мантиссы, указатель на массив с мантиссой – частным, размер – частного (длиннее на 1), указатель на массив с промежуточной экспонентой. Если старший разряд не ноль, то сдвинуть мантиссу вправо на 2-е позиции, увеличить экспоненту на 2. Если второй по старшинству разряд частного не ноль, то сдвинуть мантиссу вправо на 1-у позицию, увеличить экспоненту на 1. Если третий по старшинству разряд частного не ноль, то сдвинуть на 1-у позицию. В противном случае обнулить мантиссу.*/ { int i; if(quotient[qSize-1] != 0) { for(i = qSize-1; i > 1; i--) manti[i-2] = quotient[i]; // intToTns(eTmp, eSize+1, 2); eTmp[1] = 1; eTmp[0] = -1; addStr(exp, eSize+1, exp, eTmp); } else if(quotient[qSize-2] != 0) { eTmp[0] = 1; addStr(exp, eSize+1, exp, eTmp); for(i = qSize-1; i > 0; i--) manti[i-1] = quotient[i]; } else if(quotient[qSize-3] != 0)//? { for(i = 0; i < qSize-2; i ++) manti[i] = quotient[i]; } else { for(i = 0; i < eSize; i ++) exp[i] = 0; for(i = 0; i < mSize; i ++) manti[i] = 0; } //Проверка на переполнение if(exp[eSize] == 1) { exp[eSize] = 0; manti[mSize] = 0; for (i=0; i<eSize; i++) exp[i] = 1; for (i=0; i<mSize-1; i++) manti[i] = manti[mSize-1]; } else if (exp[eSize] == -1) { for (i=0; i<=eSize; i++) exp[i] = 0; for (i=0; i<=mSize; i++) manti[i] = 0; } }
/* Read the symbols from the object/exe specified by the SegInfo into the tables within the supplied SegInfo. */ static void vg_read_lib_symbols ( SegInfo* si ) { Elf32_Ehdr* ehdr; /* The ELF header */ Elf32_Shdr* shdr; /* The section table */ UChar* sh_strtab; /* The section table's string table */ struct nlist* stab; /* The .stab table */ UChar* stabstr; /* The .stab string table */ Int stab_sz; /* Size in bytes of the .stab table */ Int stabstr_sz; /* Size in bytes of the .stab string table */ Int fd; Int i; Bool ok; Addr oimage; Int n_oimage; struct stat stat_buf; /* for the .stabs reader */ Int curr_filenmoff; Addr curr_fnbaseaddr; Addr range_startAddr; Int range_lineno; oimage = (Addr)NULL; if (VG_(clo_verbosity) > 1) VG_(message)(Vg_UserMsg, "Reading syms from %s", si->filename ); /* mmap the object image aboard, so that we can read symbols and line number info out of it. It will be munmapped immediately thereafter; it is only aboard transiently. */ i = stat(si->filename, &stat_buf); if (i != 0) { vg_symerr("Can't stat .so/.exe (to determine its size)?!"); return; } n_oimage = stat_buf.st_size; fd = VG_(open_read)(si->filename); if (fd == -1) { vg_symerr("Can't open .so/.exe to read symbols?!"); return; } oimage = (Addr)VG_(mmap)( NULL, n_oimage, PROT_READ, MAP_PRIVATE, fd, 0 ); if (oimage == ((Addr)(-1))) { VG_(message)(Vg_UserMsg, "mmap failed on %s", si->filename ); VG_(close)(fd); return; } VG_(close)(fd); /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now verify that it is a valid ELF .so or executable image. */ ok = (n_oimage >= sizeof(Elf32_Ehdr)); ehdr = (Elf32_Ehdr*)oimage; if (ok) { ok &= (ehdr->e_ident[EI_MAG0] == 0x7F && ehdr->e_ident[EI_MAG1] == 'E' && ehdr->e_ident[EI_MAG2] == 'L' && ehdr->e_ident[EI_MAG3] == 'F'); ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_ident[EI_VERSION] == EV_CURRENT); ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN); ok &= (ehdr->e_machine == EM_386); ok &= (ehdr->e_version == EV_CURRENT); ok &= (ehdr->e_shstrndx != SHN_UNDEF); ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0); } if (!ok) { vg_symerr("Invalid ELF header, or missing stringtab/sectiontab."); VG_(munmap) ( (void*)oimage, n_oimage ); return; } if (VG_(clo_trace_symtab)) VG_(printf)( "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n", ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage ); if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) { vg_symerr("ELF section header is beyond image end?!"); VG_(munmap) ( (void*)oimage, n_oimage ); return; } shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff); sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset); /* try and read the object's symbol table */ { UChar* o_strtab = NULL; Elf32_Sym* o_symtab = NULL; UInt o_strtab_sz = 0; UInt o_symtab_sz = 0; UChar* o_got = NULL; UChar* o_plt = NULL; UInt o_got_sz = 0; UInt o_plt_sz = 0; Bool snaffle_it; Addr sym_addr; /* find the .stabstr and .stab sections */ for (i = 0; i < ehdr->e_shnum; i++) { if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) { o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset); o_symtab_sz = shdr[i].sh_size; vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0); /* check image overrun here */ } if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) { o_strtab = (UChar*)(oimage + shdr[i].sh_offset); o_strtab_sz = shdr[i].sh_size; /* check image overrun here */ } /* find out where the .got and .plt sections will be in the executable image, not in the object image transiently loaded. */ if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) { o_got = (UChar*)(si->offset + shdr[i].sh_offset); o_got_sz = shdr[i].sh_size; /* check image overrun here */ } if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) { o_plt = (UChar*)(si->offset + shdr[i].sh_offset); o_plt_sz = shdr[i].sh_size; /* check image overrun here */ } } if (VG_(clo_trace_symtab)) { if (o_plt) VG_(printf)( "PLT: %p .. %p\n", o_plt, o_plt + o_plt_sz - 1 ); if (o_got) VG_(printf)( "GOT: %p .. %p\n", o_got, o_got + o_got_sz - 1 ); } if (o_strtab == NULL || o_symtab == NULL) { vg_symerr(" object doesn't have a symbol table"); } else { /* Perhaps should start at i = 1; ELF docs suggest that entry 0 always denotes `unknown symbol'. */ for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){ # if 0 VG_(printf)("raw symbol: "); switch (ELF32_ST_BIND(o_symtab[i].st_info)) { case STB_LOCAL: VG_(printf)("LOC "); break; case STB_GLOBAL: VG_(printf)("GLO "); break; case STB_WEAK: VG_(printf)("WEA "); break; case STB_LOPROC: VG_(printf)("lop "); break; case STB_HIPROC: VG_(printf)("hip "); break; default: VG_(printf)("??? "); break; } switch (ELF32_ST_TYPE(o_symtab[i].st_info)) { case STT_NOTYPE: VG_(printf)("NOT "); break; case STT_OBJECT: VG_(printf)("OBJ "); break; case STT_FUNC: VG_(printf)("FUN "); break; case STT_SECTION: VG_(printf)("SEC "); break; case STT_FILE: VG_(printf)("FIL "); break; case STT_LOPROC: VG_(printf)("lop "); break; case STT_HIPROC: VG_(printf)("hip "); break; default: VG_(printf)("??? "); break; } VG_(printf)( ": value %p, size %d, name %s\n", si->offset+(UChar*)o_symtab[i].st_value, o_symtab[i].st_size, o_symtab[i].st_name ? ((Char*)o_strtab+o_symtab[i].st_name) : (Char*)"NONAME"); # endif /* Figure out if we're interested in the symbol. Firstly, is it of the right flavour? */ snaffle_it = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL || ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* || ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */) && (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*|| ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/) ); /* Secondly, if it's apparently in a GOT or PLT, it's really a reference to a symbol defined elsewhere, so ignore it. */ sym_addr = si->offset + (UInt)o_symtab[i].st_value; if (o_got != NULL && sym_addr >= (Addr)o_got && sym_addr < (Addr)(o_got+o_got_sz)) { snaffle_it = False; if (VG_(clo_trace_symtab)) { VG_(printf)( "in GOT: %s\n", o_strtab+o_symtab[i].st_name); } } if (o_plt != NULL && sym_addr >= (Addr)o_plt && sym_addr < (Addr)(o_plt+o_plt_sz)) { snaffle_it = False; if (VG_(clo_trace_symtab)) { VG_(printf)( "in PLT: %s\n", o_strtab+o_symtab[i].st_name); } } /* Don't bother if nameless, or zero-sized. */ if (snaffle_it && (o_symtab[i].st_name == (Elf32_Word)NULL || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */ /* equivalent but cheaper ... */ * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0 || o_symtab[i].st_size == 0)) { snaffle_it = False; if (VG_(clo_trace_symtab)) { VG_(printf)( "size=0: %s\n", o_strtab+o_symtab[i].st_name); } } # if 0 /* Avoid _dl_ junk. (Why?) */ /* 01-02-24: disabled until I find out if it really helps. */ if (snaffle_it && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0 || VG_(strncmp)("_r_debug", o_strtab+o_symtab[i].st_name, 8) == 0)) { snaffle_it = False; if (VG_(clo_trace_symtab)) { VG_(printf)( "_dl_ junk: %s\n", o_strtab+o_symtab[i].st_name); } } # endif /* This seems to significantly reduce the number of junk symbols, and particularly reduces the number of overlapping address ranges. Don't ask me why ... */ if (snaffle_it && (Int)o_symtab[i].st_value == 0) { snaffle_it = False; if (VG_(clo_trace_symtab)) { VG_(printf)( "valu=0: %s\n", o_strtab+o_symtab[i].st_name); } } /* If no part of the symbol falls within the mapped range, ignore it. */ if (sym_addr+o_symtab[i].st_size <= si->start || sym_addr >= si->start+si->size) { snaffle_it = False; } if (snaffle_it) { /* it's an interesting symbol; record ("snaffle") it. */ RiSym sym; Char* t0 = o_symtab[i].st_name ? (Char*)(o_strtab+o_symtab[i].st_name) : (Char*)"NONAME"; Int nmoff = addStr ( si, t0 ); vg_assert(nmoff >= 0 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ ); vg_assert( (Int)o_symtab[i].st_value >= 0); /* VG_(printf)("%p + %d: %s\n", si->addr, (Int)o_symtab[i].st_value, t0 ); */ sym.addr = sym_addr; sym.size = o_symtab[i].st_size; sym.nmoff = nmoff; addSym ( si, &sym ); } } } } /* Reading of the "stabs" debug format information, if any. */ stabstr = NULL; stab = NULL; stabstr_sz = 0; stab_sz = 0; /* find the .stabstr and .stab sections */ for (i = 0; i < ehdr->e_shnum; i++) { if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) { stab = (struct nlist *)(oimage + shdr[i].sh_offset); stab_sz = shdr[i].sh_size; } if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) { stabstr = (UChar*)(oimage + shdr[i].sh_offset); stabstr_sz = shdr[i].sh_size; } } if (stab == NULL || stabstr == NULL) { vg_symerr(" object doesn't have any debug info"); VG_(munmap) ( (void*)oimage, n_oimage ); return; } if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage || stabstr_sz + (UChar*)stabstr > n_oimage + (UChar*)oimage ) { vg_symerr(" ELF debug data is beyond image end?!"); VG_(munmap) ( (void*)oimage, n_oimage ); return; } /* Ok. It all looks plausible. Go on and read debug data. stab kinds: 100 N_SO a source file name 68 N_SLINE a source line number 36 N_FUN ? start of a function In this loop, we maintain a current file name, updated as N_SOs appear, and a current function base address, updated as N_FUNs appear. Based on that, address ranges for N_SLINEs are calculated, and stuffed into the line info table. N_SLINE indicates the start of a source line. Functions are delimited by N_FUNS, at the start with a non-empty string and at the end with an empty string. The latter facilitates detecting where to close the last N_SLINE for a function. */ curr_filenmoff = addStr(si,"???"); curr_fnbaseaddr = (Addr)NULL; range_startAddr = 0; range_lineno = 0; for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) { # if 0 VG_(printf) ( " %2d ", i ); VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s", stab[i].n_type, stab[i].n_other, stab[i].n_desc, (int)stab[i].n_value, (int)stab[i].n_un.n_strx, stabstr + stab[i].n_un.n_strx ); VG_(printf)("\n"); # endif switch (stab[i].n_type) { case 68: { /* N_SLINE */ /* flush the current line, if any, and start a new one */ Addr range_endAddr = curr_fnbaseaddr + (UInt)stab[i].n_value - 1; if (range_startAddr != 0) { addLineInfo ( si, curr_filenmoff, range_startAddr, range_endAddr, range_lineno ); } range_startAddr = range_endAddr + 1; range_lineno = stab[i].n_desc; break; } case 36: { /* N_FUN */ if ('\0' == * (stabstr + stab[i].n_un.n_strx) ) { /* N_FUN with no name -- indicates the end of a fn. Flush the current line, if any, but don't start a new one. */ Addr range_endAddr = curr_fnbaseaddr + (UInt)stab[i].n_value - 1; if (range_startAddr != 0) { addLineInfo ( si, curr_filenmoff, range_startAddr, range_endAddr, range_lineno ); } range_startAddr = 0; } else { /* N_FUN with a name -- indicates the start of a fn. */ curr_fnbaseaddr = si->offset + (Addr)stab[i].n_value; range_startAddr = curr_fnbaseaddr; } break; } case 100: /* N_SO */ case 132: /* N_SOL */ /* seems to give lots of locations in header files */ /* case 130: */ /* BINCL */ { UChar* nm = stabstr + stab[i].n_un.n_strx; UInt len = VG_(strlen)(nm); if (len > 0 && nm[len-1] != '/') curr_filenmoff = addStr ( si, nm ); else if (len == 0) curr_filenmoff = addStr ( si, "?1\0" ); break; } # if 0 case 162: /* EINCL */ curr_filenmoff = addStr ( si, "?2\0" ); break; # endif default: break; } } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */ /* Last, but not least, heave the oimage back overboard. */ VG_(munmap) ( (void*)oimage, n_oimage ); }