精华内容
下载资源
问答
  • 通过import引入js文件提示错误

    千次阅读 2019-04-15 14:33:55
    在js文件中通过import引入另外的js文件,提示Uncaught SyntaxError: Unexpected string,或者Uncaught SyntaxError: Unexpected identifier错误,原因是import属于es6的语法,但是浏览器不支持es6语法,所以需要转换...

    在js文件中通过import引入另外的js文件,提示Uncaught SyntaxError: Unexpected string,或者Uncaught SyntaxError: Unexpected identifier错误,原因是import属于es6的语法,但是浏览器不支持es6语法,所以需要转换。

    转换方法:

    1,用 babelimport 转成 CommonJS 或者 AMD,然后再使用requirejs或者browserify打包;

    2,使用webpack。webpack支持各种模块化规范,就vue.js来讲,有脚手架工具搭建基于webpack的开发环境,只需简单自定义的配置。

    展开全文
  • python import引入不同路径下的模块

    千次阅读 2019-10-10 14:46:46
    python 包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的路径。 下面将具体介绍几种常用情况: ...若在程序test1.py中导入模块mod1, 则直接使用 import mod1或from mod1 import *...

    python 包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的路径。
    下面将具体介绍几种常用情况:
    (1)主程序与模块程序在同一目录下:
    如下面程序结构:

    `-- src 
        |-- mod1.py 
        `-- test1.py 
    

    若在程序test1.py中导入模块mod1, 则直接使用 import mod1或from mod1 import *;

    (2)主程序所在目录是模块所在目录的父(或祖辈)目录
    如下面程序结构:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴,
    互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    `-- src 
        |-- mod1.py 
        |-- mod2 
        |   `-- mod2.py 
        `-- test1.py 
    

    若在程序test1.py中导入模块mod2, 需要在mod2文件夹中建立空文件__init__.py文件(也可以在该文件中自定义输出模块接口); 然后使用 from mod2.mod2 import * 或import mod2.mod2.

    (3)主程序导入上层目录中模块或其他目录(平级)下的模块
    如下面程序结构:

    `-- src 
        |-- mod1.py 
        |-- mod2 
        |   `-- mod2.py 
        |-- sub 
        |   `-- test2.py 
        `-- test1.py 
    

    若在程序test2.py中导入模块mod1和mod2。首先需要在mod2下建立__init__.py文件(同(2)),src下不必建立该文件。然后调用方式如下:
    下面程序执行方式均在程序文件所在目录下执行,如test2.py是在cd sub;之后执行python test2.py
    而test1.py是在cd src;之后执行python test1.py; 不保证在src目录下执行python sub/test2.py成功。

       import sys 
       sys.path.append("..") 
       import mod1 
       import mod2.mod2 
    

    (4)从(3)可以看出,导入模块关键是能够根据sys.path环境变量的值,找到具体模块的路径。这里仅介绍上面三种简单情况。

    展开全文
  • Import Table(引入表)

    千次阅读 2010-08-04 12:22:00
    文/Iczelion 译/GuFeng ...中的函数,因而命名为"import引入)"。引入函数实际位于一个或者更多的DLL里。调 用者模块里只保留一些函数信息,包括函数名及其驻留的DLL名。现在,我们怎样才能找 到P

    文/Iczelion  译/GuFeng
    
    
    本课我们将学习引入表。先警告一下,对于不熟悉引入表的读者来说,这是一堂又长又
    难的课,所以需要多读几遍,最好再打开调试器来好好分析相关结构。各位,努力啊!
    下载范例。
    
    理论:
    首先,您得了解什么是引入函数。一个引入函数是被某模块调用的但又不在调用者模块
    中的函数,因而命名为"import(引入)"。引入函数实际位于一个或者更多的DLL里。调
    用者模块里只保留一些函数信息,包括函数名及其驻留的DLL名。现在,我们怎样才能找
    到PE文件中保存的信息呢? 转到 data directory 寻求答案吧。再回顾一把,下面就是
    PE header:
    
    IMAGE_NT_HEADERS STRUCT
      Signature dd ?
      FileHeader IMAGE_FILE_HEADER <>
      OptionalHeader IMAGE_OPTIONAL_HEADER <>
    IMAGE_NT_HEADERS ENDS
    
    optional header 最后一个成员就是 data directory(数据目录):
    
    IMAGE_OPTIONAL_HEADER32 STRUCT
      ....
      LoaderFlags dd ?
      NumberOfRvaAndSizes dd ?
      DataDirectory IMAGE_DATA_DIRECTORY 16 dup(<>)
    IMAGE_OPTIONAL_HEADER32 ENDS
    
    data directory 是一个 IMAGE_DATA_DIRECTORY 结构数组,共有16个成员。如果您还记
    得节表可以看作是PE文件各节的根目录的话,也可以认为 data directory 是存储在这
    些节里的逻辑元素的根目录。明确点,data directory 包含了PE文件中各重要数据结构
    的位置和尺寸信息。每个成员包含了一个重要数据结构的信息。
    
    Member  Info inside
    0  Export symbols
    1  Import symbols
    2  Resources
    3  Exception
    4  Security
    5  Base relocation
    6  Debug
    7  Copyright string
    8  Unknown
    9  Thread local storage (TLS)
    10  Load configuration
    11  Bound Import
    12  Import Address Table
    13  Delay Import
    14  COM descriptor
    
    上面那些金色显示的是我熟悉的。了解 data directory 包含域后,我们可以仔细研究
    它们了。data directory 的每个成员都是 IMAGE_DATA_DIRECTORY 结构类型的,其定义
    如下所示:
    
    IMAGE_DATA_DIRECTORY STRUCT
     VirtualAddress dd ?
     isize dd ?
    IMAGE_DATA_DIRECTORY ENDS
    
    VirtualAddress 实际上是数据结构的相对虚拟地址(RVA)。比如,如果该结构是关于imp
    ort symbols的,该域就包含指向IMAGE_IMPORT_DESCRIPTOR 数组的RVA。
    isize 含有VirtualAddress所指向数据结构的字节数。
    
    下面就是如何找寻PE文件中重要数据结构的一般方法:
    
    从 DOS header 定位到 PE header
    从 optional header 读取 data directory 的地址。
    IMAGE_DATA_DIRECTORY 结构尺寸乘上找寻结构的索引号: 比如您要找寻import
    symbols的位置信息,必须用IMAGE_DATA_DIRECTORY 结构尺寸(8 bytes)乘上1(import
    symbols在data directory中的索引号)。
    将上面的结果加上data directory地址,我们就得到包含所查询数据结构信息的
    IMAGE_DATA_DIRECTORY 结构项。
    现在我们开始真正讨论引入表了。data directory数组第二项的VirtualAddress包含引
    入表地址。引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组。每个结构包含PE
    文件引入函数的一个相关DLL的信息。比如,如果该PE文件从10个不同的DLL中引入函数
    ,那么这个数组就有10个成员。该数组以一个全0的成员结尾。下面详细研究结构组成:
    
    IMAGE_IMPORT_DESCRIPTOR STRUCT
     union
       Characteristics dd ?
       OriginalFirstThunk dd ?
     ends
     TimeDateStamp dd ?
     ForwarderChain dd ?
     Name1 dd ?
     FirstThunk dd ?
    IMAGE_IMPORT_DESCRIPTOR ENDS
    
    结构第一项是一个union子结构。事实上,这个union子结构只是给
    OriginalFirstThunk 增添了个别名,您也可以称其为"Characteristics"。 该成员项含
    有指向一个 IMAGE_THUNK_DATA 结构数组的RVA。
    什么是 IMAGE_THUNK_DATA? 这是一个dword类型的集合。通常我们将其解释为指向一个
    IMAGE_IMPORT_BY_NAME 结构的指针。注意 IMAGE_THUNK_DATA 包含了指向一个
    IMAGE_IMPORT_BY_NAME 结构的指针: 而不是结构本身。
    请看这里: 现有几个 IMAGE_IMPORT_BY_NAME 结构,我们收集起这些结构的RVA
    (IMAGE_THUNK_DATAs)组成一个数组,并以0结尾,然后再将数组的RVA放入
    OriginalFirstThunk。
    此 IMAGE_IMPORT_BY_NAME 结构存有一个引入函数的相关信息。再来研究
    IMAGE_IMPORT_BY_NAME 结构到底是什么样子的呢:
    
    IMAGE_IMPORT_BY_NAME STRUCT
     Hint dw ?
     Name1 db ?
    IMAGE_IMPORT_BY_NAME ENDS
    
    Hint 指示本函数在其所驻留DLL的引出表中的索引号。该域被PE装载器用来在DLL的引出
    表里快速查询函数。该值不是必须的,一些连接器将此值设为0。
    Name1 含有引入函数的函数名。函数名是一个ASCIIZ字符串。注意这里虽然将Name1的大
    小定义成字节,其实它是可变尺寸域,只不过我们没有更好方法来表示结构中的可变尺
    寸域。The structure is provided so that you can refer to the data structure
    with descriptive names.
    
    
    TimeDateStamp 和 ForwarderChain 可是高级东东: 让我们精通其他成员后再来讨论它
    们吧。
    
    Name1 含有指向DLL名字的RVA,即指向DLL名字的指针,也是一个ASCIIZ字符串。
    
    FirstThunk 与 OriginalFirstThunk 非常相似,它也包含指向一个
    IMAGE_THUNK_DATA 结构数组的RVA(当然这是另外一个IMAGE_THUNK_DATA 结构数组)。
    好了,如果您还在犯糊涂,就朝这边看过来: 现在有几个 IMAGE_IMPORT_BY_NAME 结构
    ,同时您又创建了两个结构数组,并同样寸入指向那些 IMAGE_IMPORT_BY_NAME 结构的R
    VAs,这样两个数组就包含相同数值了(可谓相当精确的复制啊)。最后您决定将第一个数
    组的RVA赋给 OriginalFirstThunk,第二个数组的RVA赋给 FirstThunk,这样一切都很
    清楚了。
    
    OriginalFirstThunk   IMAGE_IMPORT_BY_NAME   FirstThunk
    |
          |
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    ...
    IMAGE_THUNK_DATA
    --->
    --->
    --->
    --->
    --->
    --->
    Function 1
    Function 2
    Function 3
    Function 4
    ...
    Function n
    <---
    <---
    <---
    <---
    <---
    <---
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    ...
    IMAGE_THUNK_DATA
    
    
    现在您应该明白我的意思。不要被IMAGE_THUNK_DATA这个名字弄糊涂: 它仅是指向
    IMAGE_IMPORT_BY_NAME 结构的RVA。 如果将 IMAGE_THUNK_DATA 字眼想象成RVA,就更
    容易明白了。OriginalFirstThunk 和 FirstThunk 所指向的这两个数组大小取决于PE文
    件从DLL中引入函数的数目。比如,如果PE文件从kernel32.dll中引入10个函数,那么IM
    AGE_IMPORT_DESCRIPTOR 结构的 Name1域包含指向字符串"kernel32.dll"的RVA,同时每
    个IMAGE_THUNK_DATA 数组有10个元素。
    
    下一个问题是: 为什么我们需要两个完全相同的数组? 为了回答该问题,我们需要了解
    当PE文件被装载到内存时,PE装载器将查找IMAGE_THUNK_DATA 和
    IMAGE_IMPORT_BY_NAME 这些结构数组,以此决定引入函数的地址。然后用引入函数真实
    地址来替代由FirstThunk指向的 IMAGE_THUNK_DATA 数组里的元素值。因此当PE文件准
    备执行时,上图已转换成:
    
    OriginalFirstThunk   IMAGE_IMPORT_BY_NAME   FirstThunk
    |
          |
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    IMAGE_THUNK_DATA
    ...
    IMAGE_THUNK_DATA
    --->
    --->
    --->
    --->
    --->
    --->
    Function 1
    Function 2
    Function 3
    Function 4
    ...
    Function n
    
     
     
     
     
     
    Address of Function 1
    Address of Function 2
    Address of Function 3
    Address of Function 4
    ...
    Address of Function n
    
    
    由OriginalFirstThunk 指向的RVA数组始终不会改变,所以若还反过头来查找引入函数
    名,PE装载器还能找寻到。
    当然再简单的事物都有其复杂的一面。有些情况下一些函数仅由序数引出,也就是说您
    不能用函数名来调用它们: 您只能用它们的位置来调用。此时,调用者模块中就不存在
    该函数的 IMAGE_IMPORT_BY_NAME 结构。不同的,对应该函数的 IMAGE_THUNK_DATA 值
    的低位字指示函数序数,而最高二进位 (MSB)设为1。例如,如果一个函数只由序数引出
    且其序数是1234h,那么对应该函数的 IMAGE_THUNK_DATA 值是80001234h。Microsoft提
    供了一个方便的常量来测试dword值的MSB位,就是 IMAGE_ORDINAL_FLAG32,其值为8000
    0000h。
    假设我们要列出某个PE文件的所有引入函数,可以照着下面步骤走:
    
    校验文件是否是有效的PE。
    从 DOS header 定位到 PE header。
    获取位于 OptionalHeader 数据目录地址。
    转至数据目录的第二个成员提取其VirtualAddress值。
    利用上值定位第一个 IMAGE_IMPORT_DESCRIPTOR 结构。
    检查 OriginalFirstThunk值。若不为0,顺着 OriginalFirstThunk 里的RVA值转入那个
    RVA数组。若 OriginalFirstThunk 为0,就改用FirstThunk值。有些连接器生成PE文件
    时会置OriginalFirstThunk值为0,这应该算是个bug。不过为了安全起见,我们还是检
    查 OriginalFirstThunk值先。
    对于每个数组元素,我们比对元素值是否等于IMAGE_ORDINAL_FLAG32。如果该元素值的
    最高二进位为1, 那么函数是由序数引入的,可以从该值的低字节提取序数。
    如果元素值的最高二进位为0,就可将该值作为RVA转入 IMAGE_IMPORT_BY_NAME 数组,
    跳过 Hint 就是函数名字了。
    再跳至下一个数组元素提取函数名一直到数组底部(它以null结尾)。现在我们已遍历完
    一个DLL的引入函数,接下去处理下一个DLL。
    即跳转到下一个 IMAGE_IMPORT_DESCRIPTOR 并处理之,如此这般循环直到数组见底。(I
    MAGE_IMPORT_DESCRIPTOR 数组以一个全0域元素结尾)。
    示例:
    本例程打开一PE文件,将所有引入函数名读入一编辑控件,同时显示
    IMAGE_IMPORT_DESCRIPTOR 结构各域值。
    
    .386
    .model flat,stdcall
    option casemap:none
    include /masm32/include/windows.inc
    include /masm32/include/kernel32.inc
    include /masm32/include/comdlg32.inc
    include /masm32/include/user32.inc
    includelib /masm32/lib/user32.lib
    includelib /masm32/lib/kernel32.lib
    includelib /masm32/lib/comdlg32.lib
    
    IDD_MAINDLG equ 101
    IDC_EDIT equ 1000
    IDM_OPEN equ 40001
    IDM_EXIT equ 40003
    
    DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
    ShowImportFunctions proto :DWORD
    ShowTheFunctions proto :DWORD,:DWORD
    AppendText proto :DWORD,:DWORD
    
    SEH struct
    PrevLink dd ? ; the address of the previous seh structure
    CurrentHandler dd ? ; the address of the new exception handler
    SafeOffset dd ? ; The offset where it's safe to continue execution
    PrevEsp dd ? ; the old value in esp
    PrevEbp dd ? ; The old value in ebp
    SEH ends
    
    .data
    AppName db "PE tutorial no.6",0
    ofn OPENFILENAME <>
    FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
                db "All Files",0,"*.*",0,0
    FileOpenError db "Cannot open the file for reading",0
    FileOpenMappingError db "Cannot open the file for memory mapping",0
    FileMappingError db "Cannot map the file into memory",0
    NotValidPE db "This file is not a valid PE",0
    CRLF db 0Dh,0Ah,0
    ImportDescriptor db 0Dh,0Ah,"================[ IMAGE_IMPORT_DESCRIPTOR
    ]=============",0
    IDTemplate db "OriginalFirstThunk = %lX",0Dh,0Ah
              db "TimeDateStamp = %lX",0Dh,0Ah
              db "ForwarderChain = %lX",0Dh,0Ah
              db "Name = %s",0Dh,0Ah
              db "FirstThunk = %lX",0
    NameHeader db 0Dh,0Ah,"Hint Function",0Dh,0Ah
              db "-----------------------------------------",0
    NameTemplate db "%u %s",0
    OrdinalTemplate db "%u (ord.)",0
    
    .data?
    buffer db 512 dup(?)
    hFile dd ?
    hMapping dd ?
    pMapping dd ?
    ValidPE dd ?
    
    .code
    start:
    invoke GetModuleHandle,NULL
    invoke DialogBoxParam, eax, IDD_MAINDLG,NULL,addr DlgProc, 0
    invoke ExitProcess, 0
    
    DlgProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    .if uMsg==WM_INITDIALOG
     invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETLIMITTEXT,0,0
    .elseif uMsg==WM_CLOSE
     invoke EndDialog,hDlg,0
    .elseif uMsg==WM_COMMAND
     .if lParam==0
       mov eax,wParam
       .if ax==IDM_OPEN
         invoke ShowImportFunctions,hDlg
       .else ; IDM_EXIT
         invoke SendMessage,hDlg,WM_CLOSE,0,0
       .endif
     .endif
    .else
     mov eax,FALSE
     ret
    .endif
    mov eax,TRUE
    ret
    DlgProc endp
    
    SEHHandler proc uses edx pExcept:DWORD, pFrame:DWORD, pContext:DWORD,
    pDispatch:DWORD
     mov edx,pFrame
     assume edx:ptr SEH
     mov eax,pContext
     assume eax:ptr CONTEXT
     push [edx].SafeOffset
     pop [eax].regEip
     push [edx].PrevEsp
     pop [eax].regEsp
     push [edx].PrevEbp
     pop [eax].regEbp
     mov ValidPE, FALSE
     mov eax,ExceptionContinueExecution
     ret
    SEHHandler endp
    
    ShowImportFunctions proc uses edi hDlg:DWORD
     LOCAL seh:SEH
     mov ofn.lStructSize,SIZEOF
     ofn mov ofn.lpstrFilter, OFFSET FilterString
     mov ofn.lpstrFile, OFFSET buffer
     mov ofn.nMaxFile,512
     mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or
    OFN_EXPLORER or OFN_HIDEREADONLY
     invoke GetOpenFileName, ADDR ofn
     .if eax==TRUE
       invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
       .if eax!=INVALID_HANDLE_value
         mov hFile, eax
         invoke CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0
         .if eax!=NULL
           mov hMapping, eax
           invoke MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0
           .if eax!=NULL
             mov pMapping,eax
             assume fs:nothing
             push fs:[0]
             pop seh.PrevLink
             mov seh.CurrentHandler,offset SEHHandler
             mov seh.SafeOffset,offset FinalExit
             lea eax,seh
             mov fs:[0], eax
             mov seh.PrevEsp,esp
             mov seh.PrevEbp,ebp
             mov edi, pMapping
             assume edi:ptr IMAGE_DOS_HEADER
             .if [edi].e_magic==IMAGE_DOS_SIGNATURE
               add edi, [edi].e_lfanew
               assume edi:ptr IMAGE_NT_HEADERS
               .if [edi].Signature==IMAGE_NT_SIGNATURE
                 mov ValidPE, TRUE
               .else
                 mov ValidPE, FALSE
               .endif
             .else
               mov ValidPE,FALSE
             .endif
    FinalExit:
             push seh.PrevLink
             pop fs:[0]
             .if ValidPE==TRUE
               invoke ShowTheFunctions, hDlg, edi
             .else
               invoke MessageBox,0, addr NotValidPE, addr AppName,
    MB_OK+MB_IConERROR
             .endif
             invoke UnmapViewOfFile, pMapping
         .else
             invoke MessageBox, 0, addr FileMappingError, addr AppName,
    MB_OK+MB_IConERROR
         .endif
         invoke CloseHandle,hMapping
       .else
         invoke MessageBox, 0, addr FileOpenMappingError, addr AppName,
    MB_OK+MB_IConERROR
       .endif
       invoke CloseHandle, hFile
      .else
      invoke MessageBox, 0, addr FileOpenError, addr AppName,
    MB_OK+MB_IConERROR
      .endif
    .endif
    ret
    ShowImportFunctions endp
    
    AppendText proc hDlg:DWORD,pText:DWORD
      invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,pText
      invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,addr CRLF
      invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETSEL,-1,0
      ret
    AppendText endp
    
    RVAToOffset PROC uses edi esi edx ecx pFileMap:DWORD,RVA:DWORD
      mov esi,pFileMap
      assume esi:ptr IMAGE_DOS_HEADER
      add esi,[esi].e_lfanew
      assume esi:ptr IMAGE_NT_HEADERS
      mov edi,RVA ; edi == RVA
      mov edx,esi
      add edx,sizeof IMAGE_NT_HEADERS
      mov cx,[esi].FileHeader.NumberOfSections
      movzx ecx,cx
      assume edx:ptr IMAGE_SECTION_HEADER
      .while ecx>0 ; check all sections
        .if edi>=[edx].VirtualAddress
          mov eax,[edx].VirtualAddress
          add eax,[edx].SizeOfRawData
          .if edi<eax ; The address is in this section
            mov eax,[edx].VirtualAddress
            sub edi,eax
            mov eax,[edx].PointerToRawData
            add eax,edi ; eax == file offset
            ret
          .endif
        .endif
        add edx,sizeof IMAGE_SECTION_HEADER
        dec ecx
      .endw
      assume edx:nothing
      assume esi:nothing
      mov eax,edi
      ret
    RVAToOffset endp
    
    ShowTheFunctions proc uses esi ecx ebx hDlg:DWORD, pNTHdr:DWORD
      LOCAL temp[512]:BYTE
      invoke SetDlgItemText,hDlg,IDC_EDIT,0
      invoke AppendText,hDlg,addr buffer
      mov edi,pNTHdr
      assume edi:ptr IMAGE_NT_HEADERS
      mov edi, [edi].OptionalHeader.DataDirectory[sizeof
    IMAGE_DATA_DIRECTORY].VirtualAddress
      invoke RVAToOffset,pMapping,edi
      mov edi,eax
      add edi,pMapping
      assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
      .while !([edi].OriginalFirstThunk==0 && [edi].TimeDateStamp==0 &&
    [edi].ForwarderChain==0 && [edi].Name1==0 && [edi].FirstThunk==0)
        invoke AppendText,hDlg,addr ImportDescriptor
        invoke RVAToOffset,pMapping, [edi].Name1
        mov edx,eax
        add edx,pMapping
        invoke wsprintf, addr temp, addr IDTemplate,
    [edi].OriginalFirstThunk,[edi].TimeDateStamp,[edi].ForwarderChain,edx,[edi].F
    irstThunk      invoke AppendText,hDlg,addr temp
        .if [edi].OriginalFirstThunk==0
           mov esi,[edi].FirstThunk
        .else
           mov esi,[edi].OriginalFirstThunk
        .endif
        invoke RVAToOffset,pMapping,esi
        add eax,pMapping
        mov esi,eax
        invoke AppendText,hDlg,addr NameHeader
        .while dword ptr [esi]!=0
          test dword ptr [esi],IMAGE_ORDINAL_FLAG32
          jnz ImportByOrdinal
          invoke RVAToOffset,pMapping,dword ptr [esi]
          mov edx,eax
          add edx,pMapping
          assume edx:ptr IMAGE_IMPORT_BY_NAME
          mov cx, [edx].Hint
          movzx ecx,cx
          invoke wsprintf,addr temp,addr NameTemplate,ecx,addr [edx].Name1
          jmp ShowTheText
    ImportByOrdinal:
          mov edx,dword ptr [esi]
          and edx,0FFFFh
          invoke wsprintf,addr temp,addr OrdinalTemplate,edx
    ShowTheText:
          invoke AppendText,hDlg,addr temp
          add esi,4
       .endw
       add edi,sizeof IMAGE_IMPORT_DESCRIPTOR
     .endw
     ret
    ShowTheFunctions endp
    end start
    
    分析:
    本例中,用户点击打开菜单显示文件打开对话框,检验文件的PE有效性后调用
    ShowTheFunctions。
    
    ShowTheFunctions proc uses esi ecx ebx hDlg:DWORD, pNTHdr:DWORD
      LOCAL temp[512]:BYTE
    
    保留512字节堆栈空间用于字符串操作。
    
      invoke SetDlgItemText,hDlg,IDC_EDIT,0
    
    清除编辑控件内容。
    
      invoke AppendText,hDlg,addr buffer
    
    将PE文件名插入编辑控件。 AppendText 通过传递一个 EM_REPLACESEL 消息以通知向编
    辑控件添加文本。然后它又向编辑控件发送一个设置了 wParam=-1和lParam=0的EM_SETS
    EL 消息,使光标定位到文本末。
    
      mov edi,pNTHdr
      assume edi:ptr IMAGE_NT_HEADERS
      mov edi, [edi].OptionalHeader.DataDirectory[sizeof
    IMAGE_DATA_DIRECTORY].VirtualAddress
    
    获取import symbols的RVA。edi起初指向 PE header,以此我们可以定位到数据目录数
    组的第二个数组元素来得到虚拟地址值。
    
      invoke RVAToOffset,pMapping,edi
      mov edi,eax
      add edi,pMapping
    
    这儿对PE编程初学者来说可能有点困难。在PE文件中大多数地址多是RVAs 而 RVAs只有
    当PE文件被PE装载器装入内存后才有意义。 本例中,我们直接将文件映射到内存而不是
    通过PE装载器载入,因此我们不能直接使用那些RVAs。必须先将那些RVAs转换成文件偏
    移量,RVAToOffset函数就起到这个作用。 这里不准备详细分析。指出的是,它还将给
    定的RVA和PE文件所有节的始末RVA作比较(检验RVA的有效性),然后通过IMAGE_SECTIO
    N_HEADER 结构中的PointerToRawData域(当然是所在节的那个PointerToRawData域啦)
    将RVA转换成文件偏移量。
    函数使用需要传递两个参数: 内存映射文件指针和所要转换的RVA。eax里返回文件偏移
    量。上面代码中,我们必须将文件偏移量加上内存映射文件指针以转换成虚拟地址。是
    不是有点复杂?
    
      assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
      .while !([edi].OriginalFirstThunk==0 && [edi].TimeDateStamp==0 &&
    [edi].ForwarderChain==0 && [edi].Name1==0 && [edi].FirstThunk==0)
    
    edi现在指向第一个 IMAGE_IMPORT_DESCRIPTOR 结构。接下来我们遍历整个结构数组直
    到遇上一个全0结构,这就是数组末尾了。
    
        invoke AppendText,hDlg,addr ImportDescriptor
        invoke RVAToOffset,pMapping, [edi].Name1
        mov edx,eax
        add edx,pMapping
    
    我们要显示当前 IMAGE_IMPORT_DESCRIPTOR 结构的值。Name1 不同于其他结构成员,它
    含有指向相关dll名的RVA。因此必须先将其转换成虚拟地址。
    
        invoke wsprintf, addr temp, addr IDTemplate,
    [edi].OriginalFirstThunk,[edi].TimeDateStamp,[edi].ForwarderChain,edx,[edi].F
    irstThunk      invoke AppendText,hDlg,addr temp
    
    显示当前 IMAGE_IMPORT_DESCRIPTOR 结构的值。
    
        .if [edi].OriginalFirstThunk==0
           mov esi,[edi].FirstThunk
        .else
           mov esi,[edi].OriginalFirstThunk
        .endif
    
    接下来准备遍历 IMAGE_THUNK_DATA 数组。通常我们会选择OriginalFirstThunk指向的
    那个数组,不过,如果某些连接器错误地将OriginalFirstThunk 置0,这可以通过检查O
    riginalFirstThunk值是否为0判断。这样的话,只要选择FirstThunk指向的数组了。
    
        invoke RVAToOffset,pMapping,esi
        add eax,pMapping
        mov esi,eax
    
    同样的,OriginalFirstThunk/FirstThunk值是一个RVA。必须将其转换为虚拟地址。
    
        invoke AppendText,hDlg,addr NameHeader
        .while dword ptr [esi]!=0
    
    现在我们准备遍历 IMAGE_THUNK_DATAs 数组以查找该DLL引入的函数名,直到遇上全0项
    。
    
          test dword ptr [esi],IMAGE_ORDINAL_FLAG32
          jnz ImportByOrdinal
    
    第一件事是校验IMAGE_THUNK_DATA 是否含有IMAGE_ORDINAL_FLAG32标记。检查IMAGE_TH
    UNK_DATA 的MSB是否为1,如果是1,则函数是通过序数引出的,所以不需要更进一步处
    理了。直接从 IMAGE_THUNK_DATA 提取低字节获得序数,然后是下一个IMAGE_THUNK_DAT
    A 双字。
    
          invoke RVAToOffset,pMapping,dword ptr [esi]
          mov edx,eax
          add edx,pMapping
          assume edx:ptr IMAGE_IMPORT_BY_NAME
    
    如果IMAGE_THUNK_DATA 的MSB是0,那么它包含了IMAGE_IMPORT_BY_NAME 结构的RVA。需
    要先转换为虚拟地址。
    
          mov cx, [edx].Hint
          movzx ecx,cx
          invoke wsprintf,addr temp,addr NameTemplate,ecx,addr [edx].Name1
          jmp ShowTheText
    
    Hint 是字类型,所以先转换为双字后再传递给wsprintf,然后我们将hint和函数名都显
    示到编辑控件中。
    
    ImportByOrdinal:
          mov edx,dword ptr [esi]
          and edx,0FFFFh
          invoke wsprintf,addr temp,addr OrdinalTemplate,edx
    
    在仅用序数引出函数的情况中,先清空高字再显示序数。
    
    ShowTheText:
          invoke AppendText,hDlg,addr temp
          add esi,4
    
    在编辑控件中插入相应的函数名/序数后,跳转到下个 IMAGE_THUNK_DATA。
    
       .endw
       add edi,sizeof IMAGE_IMPORT_DESCRIPTOR
    
    处理完当前IMAGE_THUNK_DATA 数组里的所有双字,跳转到下个IMAGE_IMPORT_DESCRIPTO
    R 开始处理其他DLLs的引入函数了。
    
    附录:
    让我们再来讨论一下bound import。当PE装载器装入PE文件时,检查引入表并将相关DLL
    s映射到进程地址空间。然后象我们这样遍历IMAGE_THUNK_DATA 数组并用引入函数的真
    实地址替换IMAGE_THUNK_DATAs 值。这一步需要很多时间。如果程序员能事先正确预测
    函数地址,PE装载器就不用每次装入PE文件时都去修正IMAGE_THUNK_DATAs 值了。Bound
     import就是这种思想的产物。
    为了方便实现,Microsoft出品的类似Visual Studio的编译器多提供了bind.exe这样的
    工具,由它检查PE文件的引入表并用引入函数的真实地址替换IMAGE_THUNK_DATA 值。当
    文件装入时,PE装载器必定检查地址的有效性,如果DLL版本不同于PE文件存放的相关信
    息,或则DLLs需要重定位,那么装载器认为原先计算的地址是无效的,它必定遍历Origi
    nalFirstThunk指向的数组以获取引入函数新地址。
    Bound import在本课中并非很重要,我们确省就是用到了OriginalFirstThunk。要了解
    更多信息可参见LUEVELSMEYER的pe.txt。 
    
    展开全文
  • Vue使用import ... from ...来导入组件,库,变量等。而from后的来源可以是js,vue,json。这个是在webpack.base.conf.js中设置的: module.exp...

    Vue使用import ... from ...来导入组件,库,变量等。而from后的来源可以是js,vue,json。这个是在webpack.base.conf.js中设置的:

    module.exports = {
          resolve: {
            extensions: ['.js', '.vue', '.json'],
            alias: {
              '@': resolve('src')
            }
          }
        ...
        }

    这里的extensions指定了from后可导入的文件类型。

    而上面定义的这3类可导入文件,js和vue是可以省略后缀的:

    import test from './test.vue'   等同于: import test from './test'

    同理:

    import test from './test.js'  等同于:import test from './test'

    json不可以省略后缀


    那么,若test.vue,test.js同时存在于同一个文件夹下,则import的导入优先级是:js>vue

     from后的来源除了文件,还可以是文件夹:import test from './components'

    该情况下的逻辑是:

        if(package.json存在 && package.main字段存在 && package.main指定的js存在) {
            取package.main指定的js作为from的来源,即使该js可能格式或内容错误
        } else if(index.js存在){
            取index.js作为from的来源
        } else {
            取index.vue作为from的来源
        }

    因此若from的来源是文件夹,那么在package.json存在且设置正确的情况下,会默认加载package.json;若不满足,则加载index.js;若不满足,则加载index.vue

    注意加载文件夹的形式,与上面省略后缀的形式是完全相同的。所以一个省略后缀的from来源,有可能是.vue,.js,或者文件夹

    例:查看Vue-Element-Admin的源码,其中有个Layout.vue:

    里面调用import导入了3个组件:

    import { Navbar, Sidebar, AppMain } from './components'。 这里,from的路径'./components'就是个文件夹。

    于是,按照前面的规则,首先查看文件夹下是否有package.json:

    并没有package.json。

    package.json不存在,那么查找index.js。index.js是存在的,于是加载。

    打开index.js:

        export { default as Navbar } from './Navbar'
         
        export { default as Sidebar } from './Sidebar'
         
        export { default as AppMain } from './AppMain'

    可以看到3个export,都没有后缀,所以其类型vue,js和文件夹都是有可能的。

    同一级目录下,存在AppMain.vue和Navbar.vue,没有同名js,所以可以判断出这两个都是加载的vue文件,即:

        export { default as Navbar } from './Navbar.vue'
         
        export { default as AppMain } from './AppMain.vue'

    而Sidebar只有一个文件夹,所以是加载的文件夹。打开Sidebar文件夹:

    优先找package.json。不存在。然后找index.js,不存在。最后找index.vue,存在。

    于是:

    export { default as Sidebar } from './Sidebar'   相当于:export { default as Sidebar } from './Sidebar/index.vue'

    这样,Layout.vue就通过加载一个文件夹,获得了3个vue组件。
    ---------------------
    原文:https://blog.csdn.net/fyyyr/article/details/83657828


    更多专业前端知识,请上【猿2048】www.mk2048.com
    展开全文
  • import、require、export、module.exports 混合使用详解 从 import 讲起 import { button, Select } from 'element-ui'这段代码到底发生了什么? babel 会将这段代码进行转码,转码之后是这个样子: var a...
  • 例:#if __has_include()#import #else#import "TestHead.h"#endif
  • jsp引入页面的3个方式 1.jstl import c:import url="inlayingJsp.jsp">c:import>  2.jsp include指令 %@ include file="inlayingJsp.jsp" %>  3.jsp include动作 jsp:include page="inlayingJsp.jsp" ...
  • python中的import、from import以及import as的区别

    万次阅读 多人点赞 2019-07-02 22:18:48
    import导入的内容只会被包含一次,在引入之前会检测是否已经存在该模块,不存在才会被引入,而include是不会做判断的。使用import在递归包含的时候不会出错,不会引起交叉编译的问题。 此外,使用include引入头文件...
  • import echarts from 'echarts' 2、引入工具类 引入工具类前需要有封装好的工具类,然后export导出相关Js工具类,一般写法如下tool.js类: export function toolFuncA(options) { return ... }, export function ...
  • 初学者 在main.js里引入本地的js或者css的时候 分不清楚 什么时候使用(这个文件是在vue项目中单独建的一个文件) import xx from './xx/.js' 什么时候使用 import './store/store.js' 这俩有什么区别吗? !...
  • ifdefine等判断后面加了import头文件的语法iOS8是不允许的,因此要把这部分移到最顶上
  • Import 引入模板(template) Import 作用域问题: import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。 Include 引入除模板外的代码组件,常用于项目...
  • 这两天在看前任的后台管理系统,看到layout布局的时候,有点不是很明白,...import { Navbar, Sidebar, Appmain } from './components' 结果按照别人的这种写法,一直报错 这是我自己写的目录结构,后来在对比的时候...
  • vue 项目动态引入css文件preface问题解决方案 preface 最新在写后台 管理, 应 业务需求, 众多菜单业务中 有个菜单需要独立出来给领导使用,改领导有独特喜欢的颜色格调。 快速开发, 只是做了菜单的权限控制, ...
  • @Import注解的作用

    万次阅读 多人点赞 2019-01-31 14:38:17
    } } 新建一个ImportConfig,在类上面加上@Configuration,加上@Configuration是为了能让Spring 扫描到这个类,并且直接通过@Import引入TestA类 @Import({TestA.class}) @Configuration public class ImportConfig { ...
  • Spring全解系列 - @Import注解

    千次阅读 2020-06-09 20:17:01
    本文基于 Spring 5.2.x @Import注解 @Import是Spring基于 Java 注解配置的主要组成部分。@Import注解提供了@Bean注解的功能,...1. 引入其他的@Configuration 假设有如下接口和两个实现类: package com.test inter.
  • @Import注解 @Import是Spring基于 Java 注解配置的主要组成部分。@Import注解提供了@Bean注解的功能,同时...1. 引入其他的@Configuration 假设有如下接口和两个实现类: package com.test interface ServiceInterfac
  • Vue + Spring Boot 项目实战(四):数据库的引入

    万次阅读 多人点赞 2019-04-14 12:20:35
    在项目中引入数据库,实现通过数据库验证用户名与密码。
  • python中的import,reload,以及__import__

    千次阅读 2017-03-14 19:00:53
    import 作用: 导入/引入一个python标准模块,其中包括.py文件、带有__init__.py文件的目录。 e.g: [python] view plaincopy  import module_name[,module1,...] from module import *|child[,child1...
  • python中__import__与import的区别

    万次阅读 2018-11-10 14:22:44
    最近在阅读一些python代码,发现有的项目里面不直接使用“import”,而是通过“__import()__”函数来导入模块。 那么这两者究竟有什么不同呢?  import导入的是一个标准模块,而标准模块的概念是一个文件夹里面...
  • import按条件导入

    2020-12-30 09:36:48
    import命令会被 JavaScript 引擎静态分析,先于模块内的其他语句执行 if (condition) { // 报错 import moduleA from './moduleA'; } import()函数 import()函数,支持动态加载模块,返回一个 Promise 对象。 ...
  • #import、#include、@import modules区别

    千次阅读 2016-04-21 14:16:36
    如果想深究,import的实现是通过#ifndef一个标志进行判断,然后在引入后#define这个标志,来避免重复引用的 实质上import也还是拷贝粘贴,这样就带来一个问题:当引用关系很复杂,或者一个头文件被非常多的...
  • 1. el表达式判断是否为空 空 不为空 不为空 ${not empty user?"非空":"空"} 2. 传值 今天需要在一个引入的公共页面传一个值进去 在对应的页面写 js可以直接取值用的 3. Bootstrap...
  • python动态import某个文件夹下的模块

    千次阅读 2014-08-14 16:30:11
    因为有 “用户上传脚本,动态运行”的需求,所以要动态地import用户上传的模块 所以写了个函数动态地import ...# -*- coding: utf-8 -*- import os import sys ... #判断传入的路径下是否有“__ini
  • 需要判断 IE11,否则IE里面的页面直接白屏且报错。 问题重现: 基于vue-quill-editor的富文本组件引入quill-image-drop-module和quill-image-resize-module的图片处理功能。 //富文本编辑器样式 import 'quill/...
  • Java静态导入(import static)

    千次阅读 2016-05-23 11:41:55
    junit测试相关代码,经常用到java 静态导入,下面简单描述java的这个特性。从Java 5 开始引入了静态导入语法(import static),其目是为了减少字符输入量,提高代码的可阅读性,以便更好地理解程序。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 140,118
精华内容 56,047
关键字:

判断import引入